source-engine/utils/hlfaceposer/curveeditorhelpers.h

371 lines
8.1 KiB
C
Raw Permalink Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef CURVEEDITORHELPERS_H
#define CURVEEDITORHELPERS_H
#ifdef _WIN32
#pragma once
#endif
#include "mxtk/mx.h"
struct CExpressionSample;
template< class T >
class CCurveEditorHelper
{
public:
CCurveEditorHelper( T *outer );
int GetBestCurveTypeForSelectedSamples( bool reflect );
int CountSelected( bool reflect );
void ChangeCurveType( bool forward, bool shiftdown, bool altdown );
void SetCurveTypeForSelectedSamples( bool reflect, int curvetype );
void SetCurveTypeForSample( int curvetype, CExpressionSample *sample );
void ToggleHoldTypeForSelectedSamples( bool reflect );
void ToggleHoldTypeForSample( CExpressionSample *sample );
bool HelperHandleEvent( mxEvent *event );
private:
T *GetOuter();
private:
T *m_pOuter;
};
template< class T >
CCurveEditorHelper<T>::CCurveEditorHelper( T *pOuter ) :
m_pOuter( pOuter )
{
Assert( pOuter );
}
template< class T >
T *CCurveEditorHelper<T>::GetOuter()
{
return m_pOuter;
}
template< class T >
int CCurveEditorHelper<T>::GetBestCurveTypeForSelectedSamples( bool reflect )
{
int numSelected = CountSelected( reflect );
if ( !numSelected )
return CURVE_DEFAULT;
CUtlMap< int, int > counts( 0, 0, DefLessFunc( int ) );
CUtlVector< T * > workList;
GetOuter()->GetWorkList( reflect, workList );
for ( int w = 0; w < workList.Count(); ++w )
{
int numSamples = workList[ w ]->NumSamples();
if ( !numSamples )
continue;
for ( int i = numSamples - 1; i >= 0 ; i-- )
{
CExpressionSample *sample = workList[ w ]->GetSample( i );
if ( !sample->selected )
continue;
int curveType = sample->GetCurveType();
int idx = counts.Find( curveType );
if ( idx == counts.InvalidIndex() )
{
idx = counts.Insert( curveType, 0 );
}
counts[ idx ]++;
}
}
int maxType = CURVE_DEFAULT;
int maxCount = -1;
for ( int i = counts.FirstInorder(); i != counts.InvalidIndex(); i = counts.NextInorder( i ) )
{
if ( counts[ i ] > maxType )
{
maxCount = counts[ i ];
maxType = counts.Key( i );
}
}
return maxType;
}
template< class T >
int CCurveEditorHelper<T>::CountSelected( bool reflect )
{
int numSelected = 0;
CUtlVector< T * > workList;
GetOuter()->GetWorkList( reflect, workList );
for ( int w = 0; w < workList.Count(); ++w )
{
int numSamples = workList[ w ]->NumSamples();
if ( !numSamples )
continue;
for ( int i = 0 ; i < numSamples; ++i )
{
CExpressionSample *sample = workList[ w ]->GetSample( i );
if ( !sample || !sample->selected )
continue;
++numSelected;
}
}
return numSelected;
}
template< class T >
void CCurveEditorHelper<T>::ChangeCurveType( bool forward, bool shiftdown, bool altdown )
{
// If holding ctrl and shift, only do inbound
bool inbound = shiftdown;
// if holding ctrl, shift + alt, do both inbound and outbound
bool outbound = !shiftdown || altdown;
// if holding ctrl + alt, do outbound
// if holding just ctrl, do outbound
int numSelected = CountSelected( false );
if ( !numSelected )
return;
int curveType = GetBestCurveTypeForSelectedSamples( false );
int sides[ 2 ];
Interpolator_CurveInterpolatorsForType( curveType, sides[ 0 ], sides[ 1 ] );
int dir = forward ? 1 : -1;
for ( int i = 0; i < 2; ++i )
{
if ( i == 0 && !inbound )
continue;
if ( i == 1 && !outbound )
continue;
sides[ i ] += dir;
if ( sides[ i ] < 0 )
{
sides[ i ] = NUM_INTERPOLATE_TYPES - 1;
}
else if ( sides[ i ] >= NUM_INTERPOLATE_TYPES )
{
sides[ i ] = INTERPOLATE_DEFAULT;
}
}
curveType = MAKE_CURVE_TYPE( sides[ 0 ], sides[ 1 ] );
SetCurveTypeForSelectedSamples( false, curveType );
}
template< class T >
void CCurveEditorHelper<T>::SetCurveTypeForSelectedSamples( bool reflect, int curvetype )
{
int numSelected = CountSelected( reflect );
if ( !numSelected )
return;
GetOuter()->PreDataChanged( "Set curve type" );
CUtlVector< T * > workList;
GetOuter()->GetWorkList( reflect, workList );
for ( int w = 0; w < workList.Count(); ++w )
{
int numSamples = workList[ w ]->NumSamples();
for ( int i = 0 ; i < numSamples; ++i )
{
CExpressionSample *sample = workList[ w ]->GetSample( i );
if ( !sample->selected )
continue;
sample->SetCurveType( curvetype );
}
}
GetOuter()->PostDataChanged( "Set curve type" );
}
template< class T >
void CCurveEditorHelper<T>::SetCurveTypeForSample( int curvetype, CExpressionSample *sample )
{
GetOuter()->PreDataChanged( "Set curve type" );
sample->SetCurveType( curvetype );
GetOuter()->PostDataChanged( "Set curve type" );
}
template< class T >
void CCurveEditorHelper<T>::ToggleHoldTypeForSelectedSamples( bool reflect )
{
int numSelected = CountSelected( reflect );
if ( !numSelected )
return;
GetOuter()->PreDataChanged( "Set hold out value" );
CUtlVector< T * > workList;
GetOuter()->GetWorkList( reflect, workList );
for ( int w = 0; w < workList.Count(); ++w )
{
int numSamples = workList[ w ]->NumSamples();
int newValue = -1;
for ( int i = 0 ; i < numSamples; ++i )
{
CExpressionSample *sample = workList[ w ]->GetSample( i );
if ( !sample->selected )
continue;
// First one controls setting
int l, r;
Interpolator_CurveInterpolatorsForType( sample->GetCurveType(), l, r );
if ( newValue == -1 )
{
newValue = ( r == INTERPOLATE_HOLD ) ? 0 : 1;
}
int newCurveType = MAKE_CURVE_TYPE( l, newValue == 1 ? INTERPOLATE_HOLD : l );
sample->SetCurveType( newCurveType );
}
}
GetOuter()->PostDataChanged( "Set hold out value" );
}
template< class T >
void CCurveEditorHelper<T>::ToggleHoldTypeForSample( CExpressionSample *sample )
{
GetOuter()->PreDataChanged( "Set hold out value" );
int l, r;
Interpolator_CurveInterpolatorsForType( sample->GetCurveType(), l, r );
if ( r == INTERPOLATE_HOLD )
{
r = l;
}
else
{
r = INTERPOLATE_HOLD;
}
int newCurveType = MAKE_CURVE_TYPE( l, r );
sample->SetCurveType( newCurveType );
GetOuter()->PostDataChanged( "Set hold out value" );
}
template< class T >
bool CCurveEditorHelper<T>::HelperHandleEvent( mxEvent *event )
{
bool handled = false;
switch ( event->event )
{
case mxEvent::KeyDown:
{
switch ( event->key )
{
default:
// Hotkey pressed
if ( event->key >= '0' &&
event->key <= '9' )
{
bool shiftdown = GetAsyncKeyState( VK_SHIFT ) ? true : false;
handled = true;
// Get curve type
int curveType = Interpolator_CurveTypeForHotkey( event->key );
if ( curveType >= 0 )
{
if ( CountSelected( shiftdown ) <= 0 )
{
GetOuter()->SetMousePositionForEvent( event );
CExpressionSample *hover = GetOuter()->GetSampleUnderMouse( event->x, event->y, 0.0f );
// Deal with highlighted item
if ( hover )
{
SetCurveTypeForSample( curveType, hover );
}
}
else
{
SetCurveTypeForSelectedSamples( shiftdown, curveType );
}
}
}
break;
case 'H':
{
handled = true;
bool shiftdown = GetAsyncKeyState( VK_SHIFT ) ? true : false;
if ( CountSelected( shiftdown ) <= 0 )
{
GetOuter()->SetMousePositionForEvent( event );
CExpressionSample *hover = GetOuter()->GetSampleUnderMouse( event->x, event->y, 0.0f );
// Deal with highlighted item
if ( hover )
{
ToggleHoldTypeForSample( hover );
}
}
else
{
ToggleHoldTypeForSelectedSamples( shiftdown );
}
}
break;
case VK_UP:
{
bool shiftdown = GetAsyncKeyState( VK_SHIFT ) ? true : false;
bool altdown = GetAsyncKeyState( VK_MENU ) ? true : false;
if ( GetAsyncKeyState( VK_CONTROL ) )
{
ChangeCurveType( false, shiftdown, altdown );
}
}
break;
case VK_DOWN:
{
bool shiftdown = GetAsyncKeyState( VK_SHIFT ) ? true : false;
bool altdown = GetAsyncKeyState( VK_MENU ) ? true : false;
if ( GetAsyncKeyState( VK_CONTROL ) )
{
ChangeCurveType( true, shiftdown, altdown );
}
}
break;
}
}
}
return handled;
}
#endif // CURVEEDITORHELPERS_H