📄 expressiontool.cpp
字号:
// Purpose:
//-----------------------------------------------------------------------------
void CExpressionToolWorkspace::ClearClickedItem( void )
{
m_nFocusItem = -1;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : force - force vert scrollbar recomputation
//-----------------------------------------------------------------------------
void CExpressionToolWorkspace::LayoutItems( bool force /* = false */ )
{
int x = TRAY_ITEM_INSET;
int y = - m_nTopOffset;
int width = w2() - 2 * TRAY_ITEM_INSET - m_nScrollbarHeight;
int height;
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
TimelineItem *item = GetItem( i );
if ( !item || !item->GetVisible() )
continue;
height = item->GetHeight();
RECT rcBounds;
rcBounds.left = x;
rcBounds.top = y;
rcBounds.right = x + width;
rcBounds.bottom = y + height;
item->SetBounds( rcBounds );
y += height + m_nItemGap;
}
if ( force || ( ComputeVPixelsNeeded() != m_nLastVPixelsNeeded ) )
{
RepositionVSlider();
}
redraw();
}
int CExpressionToolWorkspace::ComputeVPixelsNeeded( void )
{
int pixels = 0;
// Count visible
int c = 0;
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
TimelineItem *item = GetItem( i );
if ( !item || !item->GetVisible() )
continue;
c += item->GetHeight();
c += m_nItemGap;
}
pixels += c;
return pixels;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CExpressionToolWorkspace::RepositionVSlider( void )
{
int pixelsneeded = ComputeVPixelsNeeded();
if ( pixelsneeded <= ( h2() ))
{
m_pVertScrollBar->setVisible( false );
m_nTopOffset = 0;
}
else
{
m_pVertScrollBar->setVisible( true );
}
m_pVertScrollBar->setBounds(
w2() - m_nScrollbarHeight,
0,
m_nScrollbarHeight,
h2() );
m_nTopOffset = max( 0, m_nTopOffset );
m_nTopOffset = min( pixelsneeded, m_nTopOffset );
m_pVertScrollBar->setRange( 0, pixelsneeded );
m_pVertScrollBar->setValue( m_nTopOffset );
m_pVertScrollBar->setPagesize( h2() );
m_nLastVPixelsNeeded = pixelsneeded;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CExpressionToolWorkspace::DisableAllExcept( void )
{
TimelineItem *keepExpanded = GetClickedItem();
if ( !keepExpanded )
return;
g_pChoreoView->SetDirty( true );
g_pChoreoView->PushUndo( "Disable All Except" );
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
TimelineItem *item = GetItem( i );
item->SetActive( item == keepExpanded ? true : false );
}
LayoutItems();
g_pChoreoView->PushRedo( "Disable All Except" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CExpressionToolWorkspace::EnableValid( void )
{
g_pChoreoView->SetDirty( true );
g_pChoreoView->PushUndo( "Enable Valid" );
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
TimelineItem *item = GetItem( i );
item->SetActive( item->IsValid() );
}
LayoutItems();
g_pChoreoView->PushRedo( "Enable Valid" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CExpressionToolWorkspace::CollapseAll( TimelineItem *keepExpanded )
{
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
TimelineItem *item = GetItem( i );
item->SetCollapsed( item == keepExpanded ? false : true );
}
LayoutItems();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CExpressionToolWorkspace::ExpandAll( void )
{
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
TimelineItem *item = GetItem( i );
item->SetCollapsed( false );
}
LayoutItems();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CExpressionToolWorkspace::OnSnapAll()
{
g_pChoreoView->SetDirty( true );
g_pChoreoView->PushUndo( "Snap All" );
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
TimelineItem *item = GetItem( i );
item->SnapAll();
}
g_pChoreoView->PushRedo( "Snap All" );
redraw();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CExpressionToolWorkspace::OnDeleteColumn()
{
float t = g_pExpressionTool->GetTimeForClickedPos();
float snapped = FacePoser_SnapTime( t );
int scenefps = FacePoser_GetSceneFPS();
if ( scenefps <= 0 )
{
Con_Printf( "Can't delete column, scene fps is <= 0 (%i)\n", scenefps );
return;
}
int clickedframe = ( int ) ( scenefps * snapped + 0.5f );
// One half of 1/fps on each side
float epsilon = epsilon = 0.5f / (float)scenefps;
CInputParams params;
memset( ¶ms, 0, sizeof( params ) );
strcpy( params.m_szDialogTitle, "Delete Column" );
strcpy( params.m_szPrompt, "Frame(s) to delete [e.g., 82 or 81-91 ]:" );
Q_snprintf( params.m_szInputText, sizeof( params.m_szInputText ), "%i", clickedframe );
if ( !InputProperties( ¶ms ) )
return;
int deleteframestart;
int deleteframeend;
char *sep = strstr( params.m_szInputText, "-" );
if ( sep )
{
*sep = 0;
deleteframestart = atoi( params.m_szInputText );
deleteframeend = atoi( sep + 1 );
deleteframeend = max( deleteframestart, deleteframeend );
}
else
{
deleteframestart = atoi( params.m_szInputText );
deleteframeend = deleteframestart;
}
float start, end;
start = (float)deleteframestart / (float)scenefps;
end = (float)deleteframeend / (float)scenefps;
g_pChoreoView->SetDirty( true );
g_pChoreoView->PushUndo( "Delete Column" );
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
TimelineItem *item = GetItem( i );
item->DeletePoints( start - epsilon, end + epsilon );
}
g_pChoreoView->PushRedo( "Delete Column" );
redraw();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CExpressionToolWorkspace::ExpandValid( void )
{
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
TimelineItem *item = GetItem( i );
bool valid = item->IsValid();
item->SetCollapsed( !valid );
}
LayoutItems();
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
int CExpressionToolWorkspace::CountSelectedSamples( void )
{
int c = 0;
for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ )
{
TimelineItem *item = GetItem( i );
Assert( item );
item->CountSelected();
c += item->GetNumSelected();
}
return c;
}
void CExpressionToolWorkspace::MoveSelectedSamples( float dfdx, float dfdy, bool snap )
{
int selecteditems = CountSelectedSamples();
if ( !selecteditems )
return;
CChoreoEvent *e = g_pExpressionTool->GetSafeEvent();
if ( !e )
return;
float eventduration = e->GetDuration();
for ( int controller = 0; controller < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; controller++ )
{
TimelineItem *item = GetItem( controller );
if ( !item )
continue;
CFlexAnimationTrack *track = item->GetSafeTrack();
if ( !track )
continue;
int edittype = item->GetEditType();
for ( int i = 0; i < (int)track->GetNumSamples( edittype ); i++ )
{
CExpressionSample *sample = track->GetSample( i, edittype );
if ( !sample || !sample->selected )
continue;
sample->time += dfdx;
sample->time = clamp( sample->time, 0.0f, eventduration );
if ( snap )
{
sample->time = FacePoser_SnapTime( sample->time );
}
sample->value -= dfdy;
sample->value = clamp( sample->value, 0.0f, 1.0f );
}
track->Resort();
item->DrawSelf();
}
}
void CExpressionToolWorkspace::DeleteSelectedSamples( void )
{
int i, t;
int selecteditems = CountSelectedSamples();
if ( !selecteditems )
return;
g_pChoreoView->SetDirty( true );
g_pChoreoView->PushUndo( "Delete points" );
for ( int controller = 0; controller < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; controller++ )
{
TimelineItem *item = GetItem( controller );
if ( !item )
continue;
CFlexAnimationTrack *track = item->GetSafeTrack();
if ( !track )
continue;
for ( t = 0; t < 2; t++ )
{
for ( i = track->GetNumSamples( t ) - 1; i >= 0 ; i-- )
{
CExpressionSample *sample = track->GetSample( i, t );
if ( !sample->selected )
continue;
track->RemoveSample( i, t );
}
}
item->DrawSelf();
}
g_pChoreoView->PushRedo( "Delete points" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CExpressionToolWorkspace::DeselectAll( void )
{
int i, t;
int selecteditems = CountSelectedSamples();
if ( !selecteditems )
return;
for ( int controller = 0; controller < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; controller++ )
{
TimelineItem *item = GetItem( controller );
if ( !item )
continue;
CFlexAnimationTrack *track = item->GetSafeTrack();
if ( !track )
continue;
for ( t = 0; t < 2; t++ )
{
for ( i = track->GetNumSamples( t ) - 1; i >= 0 ; i-- )
{
CExpressionSample *sample = track->GetSample( i, t );
sample->selected = false;
}
}
item->DrawSelf();
}
}
void CExpressionToolWorkspace::SelectPoints( float start, float end )
{
int i, t;
for ( int controller = 0; controller < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; controller++ )
{
TimelineItem *item = GetItem( controller );
if ( !item )
continue;
CFlexAnimationTrack *track = item->GetSafeTrack();
if ( !track )
continue;
for ( t = 0; t < 2; t++ )
{
for ( i = track->GetNumSamples( t ) - 1; i >= 0 ; i-- )
{
CExpressionSample *sample = track->GetSample( i, t );
bool inrange = ( sample->time >= start && sample->time <= end );
sample->selected = inrange;
}
}
item->DrawSelf();
}
}
ExpressionTool::ExpressionTool( mxWindow *parent )
: IFacePoserToolWindow( "ExpressionTool", "Flex Animation" ), mxWindow( parent, 0, 0, 0, 0 )
{
m_bSuppressLayout = false;
SetAutoProcess( true );
m_pWorkspace = new CExpressionToolWorkspace( this );
m_szEvent[0] = 0;
m_flScrub = 0.0f;
m_flScrubTarget = 0.0f;
m_nDragType = DRAGTYPE_NONE;
m_nClickedX = 0;
m_nClickedY = 0;
m_hPrevCursor = 0;
m_nStartX = 0;
m_nStartY = 0;
m_nMinX = 0;
m_nMaxX = 0;
m_bUseBounds = false;
m_pLastEvent = NULL;
m_nMousePos[ 0 ] = m_nMousePos[ 1 ] = 0;
m_flSelection[ 0 ] = m_flSelection[ 1 ] = 0.0f;
m_bSelectionActive = false;
m_bLayoutIsValid = false;
m_flPixelsPerSecond = 500.0f;
m_flLastDuration = 0.0f;
m_nTimeZoom = 100;
m_nScrollbarHeight = 12;
m_nLeftOffset = 0;
m_nLastHPixelsNeeded = -1;
m_pHorzScrollBar = new mxScrollbar( this, 0, 0, 18, 100, IDC_FLEXHSCROLL, mxScrollbar::Horizontal );
m_pHorzScrollBar->setVisible( false );
m_bInSetEvent = false;
m_flScrubberTimeOffset = 0.0f;
}
ExpressionTool::~ExpressionTool( void )
{
}
void ExpressionTool::DoTrackLookup( CChoreoEvent *event )
{
if ( !event || !models->GetActiveStudioModel() )
return;
//if ( event->GetTrackLookupSet() )
// return;
// Force recompute
SetEvent( event );
}
#pragma optimize( "g", off )
void ExpressionTool::SetEvent( CChoreoEvent *event )
{
if ( m_bInSetEvent )
return;
m_bInSetEvent = true;
if ( event == m_pLastEvent )
{
if ( event )
{
float dur = event->GetDuration();
if ( dur != m_flLastDuration )
{
m_flLastDuration = dur;
m_nLastHPixelsNeeded = -1;
m_nLeftOffset = 0;
InvalidateLayout();
}
}
m_bInSetEvent = false;
return;
}
m_pLastEvent = event;
m_pWorkspace->HideTimelines();
m_szEvent[ 0 ] = 0;
if ( event )
{
strcpy( m_szEvent, event->GetName() );
if ( models->GetActiveStudioModel() )
{
studiohdr_t *hdr = models->GetActiveStudioModel()->getStudioHeader ();
if ( hdr )
{
// Force re-lookup
event->SetTrackLookupSet( false );
SetupFlexControllerTracks( hdr, event );
int itemCount = 0;
for ( int i = 0; i < event->GetNumFlexAnimationTracks(); i++ )
{
CFlexAnimationTrack *track = event->GetFlexAnimationTrack( i );
Assert( track );
if ( !track )
continue;
TimelineItem *item = m_pWorkspace->GetItem( itemCount++ );
item->SetExpressionInfo( track, track->GetFlexControllerIndex( 0 ) );
item->SetCollapsed( track->GetNumSamples( 0 ) <= 0 );
item->SetVisible( true );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -