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