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.
370 lines
8.1 KiB
370 lines
8.1 KiB
//========= 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
|
|
|