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 |
|
|
|
|