diff options
Diffstat (limited to 'utils/hlfaceposer/flexpanel.cpp')
| -rw-r--r-- | utils/hlfaceposer/flexpanel.cpp | 1092 |
1 files changed, 1092 insertions, 0 deletions
diff --git a/utils/hlfaceposer/flexpanel.cpp b/utils/hlfaceposer/flexpanel.cpp new file mode 100644 index 0000000..c268d51 --- /dev/null +++ b/utils/hlfaceposer/flexpanel.cpp @@ -0,0 +1,1092 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + + +#include "hlfaceposer.h" +#include "FlexPanel.h" +#include "ViewerSettings.h" +#include "StudioModel.h" +#include "MatSysWin.h" +#include "ControlPanel.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <mxtk/mx.h> +#include <mxtk/mxBmp.h> + +#include "mxbitmapwindow.h" +#include "mxExpressionTray.h" +#include "expressions.h" +#include "expressiontool.h" +#include "filesystem.h" +#include "mdlviewer.h" +#include "ExpressionProperties.h" +#include "expclass.h" +#include "choreowidgetdrawhelper.h" +#include "choreoview.h" +#include "choreoscene.h" +#include "mxExpressionSlider.h" +#include "faceposer_models.h" + +LocalFlexController_t FindFlexControllerIndexByName( StudioModel *model, char const *searchname ); +char const *GetGlobalFlexControllerName( int index ); + +extern char g_appTitle[]; + +#define LINE_HEIGHT 20 + +#define FLEXSLIDER_INVALID_INDEX -1 + +FlexPanel *g_pFlexPanel = 0; + +void FlexPanel::PositionControls( int width, int height ) +{ + int buttonwidth = 80; + int buttonx = 3; + int row = height - 18; + int buttonheight = 18; + + btnResetSliders->setBounds( buttonx, row, buttonwidth, buttonheight ); + + buttonx += buttonwidth + 5; + btnCopyToSliders->setBounds( buttonx, row, buttonwidth, buttonheight ); + + buttonx += buttonwidth + 5; + buttonwidth = 100; + btnCopyFromSliders->setBounds( buttonx, row, buttonwidth, buttonheight ); + + buttonx += buttonwidth + 5; + buttonwidth = 100; + + btnMenu->setBounds( buttonx, row, buttonwidth, buttonheight ); +} + +FlexPanel::FlexPanel (mxWindow *parent) +: IFacePoserToolWindow( "FlexPanel", "Flex Sliders" ), mxWindow( parent, 0, 0, 0, 0 ) +{ + m_nViewableFlexControllerCount = 0; + + m_bNewExpressionMode = true; + + btnResetSliders = new mxButton( this, 0, 0, 100, 20, "Zero Sliders", IDC_EXPRESSIONRESET ); + + btnCopyToSliders = new mxButton( this, 0, 0, 100, 20, "Get Tracks", IDC_COPY_TO_FLEX ); + btnCopyFromSliders = new mxButton( this, 0, 0, 100, 20, "Make Keyframe", IDC_COPY_FROM_FLEX ); + btnMenu = new mxButton( this, 0, 0, 100, 20, "Menu", IDC_FP_MENU ); + + mxWindow *wFlex = this; + for (int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++) + { + int w = 5; // (i / 4) * 156 + 5; + int h = i * LINE_HEIGHT + 5; // (i % 4) * 20 + 5; + + slFlexScale[i] = new mxExpressionSlider (wFlex, w, h, 220, LINE_HEIGHT, IDC_FLEXSCALE + i); + } + + slScrollbar = new mxScrollbar( wFlex, 0, 0, 18, 100, IDC_FLEXSCROLL, mxScrollbar::Vertical ); + slScrollbar->setRange( 0, GLOBAL_STUDIO_FLEX_CONTROL_COUNT * LINE_HEIGHT ); + slScrollbar->setPagesize( 100 ); +} + + + +FlexPanel::~FlexPanel() +{ +} + +void FlexPanel::redraw() +{ + if ( !ToolCanDraw() ) + return; + + CChoreoWidgetDrawHelper helper( this, GetSysColor( COLOR_BTNFACE ) ); + HandleToolRedraw( helper ); + + BaseClass::redraw(); +} + +void FlexPanel::PositionSliders( int sboffset ) +{ + int reservedheight = GetCaptionHeight() + 5 /*gap at top*/ + 1 * 20 /* space for buttons/edit controls*/; + + int widthofslidercolumn = slFlexScale[ 0 ]->w() + 10; + + int colsavailable = ( this->w2() - 20 /*scrollbar*/ - 10 /*left edge gap + right gap*/ ) / widthofslidercolumn; + // Need at least one column + colsavailable = max( colsavailable, 1 ); + + int rowsneeded = GLOBAL_STUDIO_FLEX_CONTROL_COUNT; + + CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr(); + if ( hdr ) + { + rowsneeded = m_nViewableFlexControllerCount; + } + + int rowsvisible = ( this->h2() - reservedheight ) / LINE_HEIGHT; + + int rowspercol = rowsvisible; + + if ( rowsvisible * colsavailable < rowsneeded ) + { + // Figure out how many controls should go in each available column + rowspercol = (rowsneeded + (colsavailable - 1)) / colsavailable; + + slScrollbar->setPagesize( rowsvisible * LINE_HEIGHT ); + slScrollbar->setRange( 0, rowspercol * LINE_HEIGHT ); + } + + int row = 0; + int col = 0; + for (int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++) + { + int x = 5 + col * widthofslidercolumn; + int y = row * LINE_HEIGHT + 5 + GetCaptionHeight() - sboffset; // (i % 4) * 20 + 5; + + slFlexScale[ i ]->setBounds( x, y, slFlexScale[i]->w(), slFlexScale[i]->h() ); + + if ( i >= rowsneeded || + ( y + LINE_HEIGHT - 5 > ( this->h2() - reservedheight ) ) ) + { + slFlexScale[ i ]->setVisible( false ); + } + else + { + slFlexScale[ i ]->setVisible( true ); + } + + row++; + if ( row >= rowspercol ) + { + col++; + row = 0; + } + } +} + +int FlexPanel::handleEvent (mxEvent *event) +{ + MDLCACHE_CRITICAL_SECTION_( g_pMDLCache ); + + int iret = 0; + + if ( HandleToolEvent( event ) ) + { + return iret; + } + + switch ( event->event ) + { + case mxEvent::Size: + { + int trueh = h2() - GetCaptionHeight(); + PositionControls( w2(), h2() ); + slScrollbar->setPagesize( trueh ); + slScrollbar->setBounds( w2() - 18, GetCaptionHeight(), 18, trueh ); + PositionSliders( 0 ); + iret = 1; + } + break; + case mxEvent::Action: + { + iret = 1; + switch ( event->action ) + { + default: + iret = 0; + break; + case IDC_FLEXSCROLL: + { + if ( event->event == mxEvent::Action && + event->modifiers == SB_THUMBTRACK) + { + int offset = event->height; // ((mxScrollbar *) event->widget)->getValue( ); + + slScrollbar->setValue( offset ); // if (offset > slScrollbar->getPagesize() + + PositionSliders( offset ); + + IFacePoserToolWindow::SetActiveTool( this ); + } + } + break; + case IDC_EXPRESSIONRESET: + { + ResetSliders( true, true ); + IFacePoserToolWindow::SetActiveTool( this ); + } + break; + + case IDC_COPY_TO_FLEX: + { + g_pExpressionTool->OnCopyToFlex( g_pChoreoView->GetScene()->GetTime(), true ); + } + break; + case IDC_COPY_FROM_FLEX: + { + g_pExpressionTool->OnCopyFromFlex( g_pChoreoView->GetScene()->GetTime(), false ); + } + break; + case IDC_FP_UNCHECK_ALL: + { + OnSetAll( FP_STATE_UNCHECK ); + } + break; + case IDC_FP_CHECK_ALL: + { + OnSetAll( FP_STATE_CHECK ); + } + break; + case IDC_FP_INVERT: + { + OnSetAll( FP_STATE_INVERT ); + } + break; + case IDC_FP_MENU: + { + OnMenu(); + } + break; + } + + if ( event->action >= IDC_FLEXSCALE && event->action < IDC_FLEXSCALE + GLOBAL_STUDIO_FLEX_CONTROL_COUNT) + { + iret = 1; + + bool pushundo = false; + + mxExpressionSlider *slider = ( mxExpressionSlider * )event->widget; + int barnumber = event->height; + int slidernum = ( event->action - IDC_FLEXSCALE ); + + float value = slider->getValue ( barnumber ); + float influ = slider->getInfluence( ); + + switch( event->modifiers ) + { + case SB_THUMBPOSITION: + case SB_THUMBTRACK: + break; + case SB_ENDSCROLL: + pushundo = true; + break; + } + int flex = LookupFlex( slidernum, barnumber ); + int flex2 = LookupPairedFlex( flex ); + float value2 = GetSlider( flex2 ); + + CExpClass *active = expressions->GetActiveClass(); + if ( active ) + { + int index = active->GetSelectedExpression(); + if ( pushundo && index != -1 ) + { + CExpression *exp = active->GetExpression( index ); + if ( exp ) + { + float *settings = exp->GetSettings(); + float *weights = exp->GetWeights(); + Assert( settings ); + + if ( settings[ flex ] != value || + settings[ flex2 ] != value2 || + weights[ flex ] != influ ) + { + exp->PushUndoInformation(); + + active->SetDirty( true ); + + settings[ flex ] = value; + settings[ flex2 ] = value2; + weights[ flex ] = influ; + weights[ flex2 ] = influ; + + exp->PushRedoInformation(); + + g_pExpressionTrayTool->redraw(); + } + } + } + } + + // FIXME: Needs to drive the current actor, not model + + // Go from global to local indices + LocalFlexController_t localflex = FindFlexControllerIndexByName( models->GetActiveStudioModel(), GetGlobalFlexControllerName( flex ) ); + if ( localflex >= 0 ) + { + // Update the face + // FIXME: I'm not sure this is needed anymore.... + models->GetActiveStudioModel()->SetFlexController( localflex, value * influ ); + if (flex2 != flex) + { + LocalFlexController_t localflex2 = FindFlexControllerIndexByName( models->GetActiveStudioModel(), GetGlobalFlexControllerName( flex2 ) ); + if ( localflex2 >= 0 ) + { + models->GetActiveStudioModel()->SetFlexController( localflex2, value2 * influ ); + } + else + { + Assert( 0 ); + } + } + } + else + { + Assert( 0 ); + } + + models->SetSolveHeadTurn( 1 ); + IFacePoserToolWindow::SetActiveTool( this ); + } + } + } + + return iret; +} + +void FlexPanel::initFlexes() +{ + m_nViewableFlexControllerCount = 0; + + memset( nFlexSliderIndex, 0, sizeof( nFlexSliderIndex ) ); + memset( nFlexSliderBarnum, 0, sizeof( nFlexSliderBarnum ) ); + + CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr(); + if (hdr) + { + for (int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++) + { + slFlexScale[i]->setVisible( false ); + slFlexScale[i]->setLabel( "" ); + slFlexScale[i]->SetMode( false ); + // init to invalid slider index + nFlexSliderIndex[i] = FLEXSLIDER_INVALID_INDEX; + } + + // J is the slider number we're filling in + int j = 0; + for ( LocalFlexController_t k = LocalFlexController_t(0); k < hdr->numflexcontrollers(); k++ ) + { + // Lookup global flex controller index + int controller = hdr->pFlexcontroller( k )->localToGlobal; + Assert( controller != -1 ); + + // Con_Printf( "%i Setting up %s global %i\n", k, hdr->pFlexcontroller(k)->pszName(), controller ); + + slFlexScale[j]->setLabel( hdr->pFlexcontroller(k)->pszName() ); + + if ( nFlexSliderIndex[controller] == FLEXSLIDER_INVALID_INDEX ) + { + //Con_Printf( "Assigning bar %i to barnum %i of slider %s for controller %i\n", + // j, 0, hdr->pFlexcontroller(k)->pszName(), controller ); + + nFlexSliderIndex[controller] = j; + nFlexSliderBarnum[controller] = 0; + } + else + { + Assert( 0 ); + } + + if (hdr->pFlexcontroller(k)->min != hdr->pFlexcontroller(k)->max) + slFlexScale[j]->setRange( 0, hdr->pFlexcontroller(k)->min, hdr->pFlexcontroller(k)->max ); + + if (strncmp( "right_", hdr->pFlexcontroller(k)->pszName(), 6 ) == 0) + { + if (hdr->pFlexcontroller(k)->min != hdr->pFlexcontroller(k)->max) + slFlexScale[j]->setRange( 1, 0.0f, 1.0f ); + slFlexScale[j]->setLabel( &hdr->pFlexcontroller(k)->pszName()[6] ); + + slFlexScale[j]->SetMode( true ); + k++; + controller = hdr->pFlexcontroller( k )->localToGlobal; + Assert( controller != -1 ); + if ( nFlexSliderIndex[controller] == FLEXSLIDER_INVALID_INDEX ) + { + nFlexSliderIndex[controller] = j; + nFlexSliderBarnum[controller] = 1; + + //Con_Printf( "Assigning stereo side of bar %i to barnum %i of slider %s for controller\n", + // j, 1, hdr->pFlexcontroller(k)->pszName(), controller ); + + } + else + { + Assert(0); + } + } + m_nViewableFlexControllerCount++; + + slFlexScale[j]->setVisible( true ); + slFlexScale[j]->redraw(); + + j++; + } + } + + slScrollbar->setRange( 0, m_nViewableFlexControllerCount * LINE_HEIGHT + 5 ); + + int trueh = h2() - GetCaptionHeight(); + PositionControls( w2(), h2() ); + slScrollbar->setPagesize( trueh ); + slScrollbar->setBounds( w2() - 18, GetCaptionHeight(), 18, trueh ); + PositionSliders( 0 ); +} + + +void FlexPanel::OnModelChanged() +{ + ResetSliders( true, false ); + SetEvent( NULL ); + redraw(); +} + +void FlexPanel::SetEvent( CChoreoEvent *event ) +{ + bool bUpdateSliders = false; + + if ( event != NULL ) + { + CChoreoScene *scene = event->GetScene(); + StudioModel *model = FindAssociatedModel( scene, event->GetActor() ); + + if (model == models->GetActiveStudioModel()) + { + bUpdateSliders = true; + } + } + + btnCopyToSliders->setEnabled( bUpdateSliders ); + btnCopyFromSliders->setEnabled( bUpdateSliders ); + return; +} + + +bool FlexPanel::IsValidSlider( int iFlexController ) const +{ + if ( nFlexSliderIndex[ iFlexController ] == FLEXSLIDER_INVALID_INDEX ) + return false; + + return true; +} + +float +FlexPanel::GetSlider( int iFlexController ) +{ + if ( !IsValidSlider( iFlexController ) ) + { + Msg( "GetSlider(%d) invalid controller index\n", iFlexController ); + return 0.0f; + } + + return slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->getValue( nFlexSliderBarnum[ iFlexController ] ); +} + +float FlexPanel::GetSliderRawValue( int iFlexController ) +{ + if ( !IsValidSlider( iFlexController ) ) + { + Msg( "GetSliderRawValue(%d) invalid controller index\n", iFlexController ); + return 0.0f; + } + + return slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->getRawValue( nFlexSliderBarnum[ iFlexController ] ); +} + +void FlexPanel::GetSliderRange( int iFlexController, float& minvalue, float& maxvalue ) +{ + int barnum = nFlexSliderBarnum[ iFlexController ]; + + if ( !IsValidSlider( iFlexController ) ) + { + Msg( "GetSliderRange(%d) invalid controller index\n", iFlexController ); + + minvalue = 0.0f; + maxvalue = 1.0f; + return; + } + + mxExpressionSlider *sl = slFlexScale[ nFlexSliderIndex[ iFlexController ] ]; + Assert( sl ); + minvalue = sl->getMinValue( barnum ); + maxvalue = sl->getMaxValue( barnum ); +} + +void +FlexPanel::SetSlider( int iFlexController, float value ) +{ + if ( !IsValidSlider( iFlexController ) ) + { + Msg( "SetSlider(%d) invalid controller index\n", iFlexController ); + return; + } + + slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->setValue( nFlexSliderBarnum[ iFlexController ], value ); +} + +float +FlexPanel::GetInfluence( int iFlexController ) +{ + if ( !IsValidSlider( iFlexController ) ) + { + Msg( "GetInfluence(%d) invalid controller index\n", iFlexController ); + return 0.0f; + } + + return slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->getInfluence( ); +} + +void +FlexPanel::SetEdited( int iFlexController, bool isEdited ) +{ + if ( !IsValidSlider( iFlexController ) ) + { + Msg( "IsEdited(%d) invalid controller index\n", iFlexController ); + return; + } + + slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->setEdited( nFlexSliderBarnum[ iFlexController ], isEdited ); +} + +bool +FlexPanel::IsEdited( int iFlexController ) +{ + if ( !IsValidSlider( iFlexController ) ) + { + Msg( "IsEdited(%d) invalid controller index\n", iFlexController ); + return 0.0f; + } + + return slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->isEdited( nFlexSliderBarnum[ iFlexController ] ); +} + +void +FlexPanel::SetInfluence( int iFlexController, float value ) +{ + if ( !IsValidSlider( iFlexController ) ) + { + Msg( "SetInfluence(%d) invalid controller index\n", iFlexController ); + return; + } + + // Con_Printf( "SetInfluence( %d, %.0f ) : %d %d\n", iFlexController, value, nFlexSliderIndex[ iFlexController ], nFlexSliderBarnum[ iFlexController ] ); + if ( nFlexSliderBarnum[ iFlexController ] == 0) + { + slFlexScale[ nFlexSliderIndex[ iFlexController ] ]->setInfluence( value ); + } +} + +int +FlexPanel::LookupFlex( int iSlider, int barnum ) +{ + for (int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++) + { + if (nFlexSliderIndex[i] == iSlider && nFlexSliderBarnum[i] == barnum) + { + // char const *name = GetGlobalFlexControllerName( i ); + //Con_Printf( "lookup slider %i bar %i == %s\n", + //iSlider, barnum, name ); + + return i; + } + } + + Con_Printf( "lookup slider %i bar %i failed\n", + iSlider, barnum); + return 0; +} + + +int +FlexPanel::LookupPairedFlex( int iFlexController ) +{ + if ( !IsValidSlider( iFlexController ) ) + { + Msg( "LookupPairedFlex(%d) invalid controller index\n", iFlexController ); + return iFlexController; + } + + if (nFlexSliderBarnum[ iFlexController ] == 1) + { + return iFlexController - 1; + } + else if (nFlexSliderIndex[ iFlexController + 1 ] == nFlexSliderIndex[ iFlexController ]) + { + return iFlexController + 1; + } + return iFlexController; +} + +void +FlexPanel::setExpression( int index ) +{ + if ( !models->GetActiveStudioModel() ) + return; + + CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr(); + if ( !hdr ) + return; + + CExpClass *active = expressions->GetActiveClass(); + if ( !active ) + return; + + CExpression *exp = active->GetExpression( index ); + if ( !exp ) + return; + + // Con_Printf( "Setting expression to %i:'%s'\n", index, exp->name ); + + float *settings = exp->GetSettings(); + float *weights = exp->GetWeights(); + Assert( settings ); + Assert( weights ); + + for (LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++) + { + int j = hdr->pFlexcontroller( i )->localToGlobal; + if ( j == -1 ) + continue; + + //if ( weights[j] > 0.0f ) + //{ + // Con_Printf( "%i Setting %s to %f\n", j, GetGlobalFlexControllerName( j ), + // settings[ j ] ); + //} + + SetSlider( j, settings[j] ); + SetInfluence( j, weights[j] ); + models->GetActiveStudioModel()->SetFlexController( i, settings[j] * weights[j] ); + } +} + +void FlexPanel::DeleteExpression( int index ) +{ + CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr(); + if ( !hdr ) + return; + CExpClass *active = expressions->GetActiveClass(); + if ( !active ) + return; + + CExpression *exp = active->GetExpression( index ); + if ( !exp ) + return; + + active->DeleteExpression( exp->name ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : index - +//----------------------------------------------------------------------------- +void FlexPanel::RevertExpression( int index ) +{ + CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr(); + if ( !hdr ) + return; + + CExpClass *active = expressions->GetActiveClass(); + if ( !active ) + return; + + CExpression *exp = active->GetExpression( index ); + if ( !exp ) + return; + + exp->Revert(); + setExpression( index ); + g_pExpressionTrayTool->redraw(); +} + +void FlexPanel::SaveExpression( int index ) +{ + CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr(); + if ( !hdr ) + return; + + CExpClass *active = expressions->GetActiveClass(); + if ( !active ) + return; + + CExpression *exp = active->GetExpression( index ); + if ( !exp ) + return; + + int retval = mxMessageBox( this, "Overwrite existing expression?", g_appTitle, MX_MB_YESNO | MX_MB_QUESTION ); + if ( retval != 0 ) + return; + + float *settings = exp->GetSettings(); + float *weights = exp->GetWeights(); + Assert( settings ); + Assert( weights ); + for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++ ) + { + int j = hdr->pFlexcontroller( i )->localToGlobal; + + settings[ j ] = GetSlider( j ); + weights[ j ] = GetInfluence( j ); + } + + exp->CreateNewBitmap( models->GetActiveModelIndex() ); + + exp->ResetUndo(); + + exp->SetDirty( false ); + + g_pExpressionTrayTool->redraw(); +} + +void FlexPanel::CopyControllerSettingsToStructure( CExpression *exp ) +{ + Assert( exp ); + + CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr(); + if ( hdr ) + { + float *settings = exp->GetSettings(); + float *weights = exp->GetWeights(); + + for (LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++) + { + int j = hdr->pFlexcontroller( i )->localToGlobal; + + settings[ j ] = GetSlider( j ); + weights[ j ] = GetInfluence( j ); + } + } +} + +void FlexPanel::OnSetAll( int state ) +{ + CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr(); + if ( hdr ) + { + for (LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++) + { + int j = hdr->pFlexcontroller( i )->localToGlobal; + + float setting = GetSlider( j ); + float influence = GetInfluence( j ); + switch ( state ) + { + default: + Assert( 0 ); + break; + case FP_STATE_UNCHECK: + influence = 0.0f; + break; + case FP_STATE_CHECK: + influence = 1.0f; + break; + case FP_STATE_INVERT: + influence = 1.0f - influence; + break; + } + + SetInfluence( j, influence ); + models->GetActiveStudioModel()->SetFlexController( i, setting * influence ); + } + } +} + +void FlexPanel::ResetSliders( bool preserveundo, bool bDirtyClass ) +{ + CExpClass *active = expressions->GetActiveClass(); + + bool needredo = false; + CExpression zeroes; + + CExpression *exp = NULL; + if ( active ) + { + int index = active->GetSelectedExpression(); + if ( index != -1 ) + { + exp = active->GetExpression( index ); + if ( exp ) + { + float *settings = exp->GetSettings(); + Assert( settings ); + + if ( memcmp( settings, zeroes.GetSettings(), GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ) ) + { + if ( preserveundo ) + { + exp->PushUndoInformation(); + needredo = true; + } + + if ( bDirtyClass ) + { + active->SetDirty( true ); + } + + g_pExpressionTrayTool->redraw(); + } + } + } + } + + CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr(); + if ( hdr ) + { + if( exp ) + { + float *settings = exp->GetSettings(); + float *weights = exp->GetWeights(); + + Assert( settings && weights ); + + for ( int i = 0; i < GLOBAL_STUDIO_FLEX_CONTROL_COUNT; i++ ) + { + settings[ i ] = 0.0f; + weights[ i ] = 0.0f; + } + } + + for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++ ) + { + int j = hdr->pFlexcontroller( i )->localToGlobal; + + if ( j == -1 ) + continue; + + SetSlider( j, 0.0f ); + SetInfluence( j, 0.0f ); + SetEdited( j, false ); + models->GetActiveStudioModel()->SetFlexController( i, 0.0f ); + } + } + + if ( exp && needredo && preserveundo ) + { + exp->PushRedoInformation(); + } +} + +void FlexPanel::CopyControllerSettings( void ) +{ + CExpression *exp = expressions->GetCopyBuffer(); + memset( exp, 0, sizeof( *exp ) ); + CopyControllerSettingsToStructure( exp ); +} + +void FlexPanel::PasteControllerSettings( void ) +{ + CExpClass *active = expressions->GetActiveClass(); + if ( !active ) + return; + + bool needredo = false; + CExpression *paste = expressions->GetCopyBuffer(); + if ( !paste ) + return; + + CExpression *exp = NULL; + int index = active->GetSelectedExpression(); + if ( index != -1 ) + { + exp = active->GetExpression( index ); + if ( exp ) + { + float *settings = exp->GetSettings(); + Assert( settings ); + + // UPDATEME + if ( memcmp( settings, paste->GetSettings(), GLOBAL_STUDIO_FLEX_CONTROL_COUNT * sizeof( float ) ) ) + { + exp->PushUndoInformation(); + needredo = true; + + active->SetDirty( true ); + + g_pExpressionTrayTool->redraw(); + } + } + } + + CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr(); + if ( hdr ) + { + float *settings = paste->GetSettings(); + float *weights = paste->GetWeights(); + Assert( settings ); + Assert( weights ); + + for (LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++) + { + int j = hdr->pFlexcontroller( i )->localToGlobal; + + SetSlider( j, settings[j] ); + SetInfluence( j, weights[j] ); + models->GetActiveStudioModel()->SetFlexController( i, settings[j] * weights[j] ); + } + } + + if ( exp && needredo ) + { + exp->PushRedoInformation(); + } + +} + +void FlexPanel::EditExpression( void ) +{ + CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr(); + if ( !hdr ) + { + Con_ErrorPrintf( "Can't edit face pose, must load a model first!\n" ); + return; + } + + CExpClass *active = expressions->GetActiveClass(); + if ( !active ) + return; + + int index = active->GetSelectedExpression(); + if ( index == -1 ) + { + Con_ErrorPrintf( "Can't edit face pose, must select a face from list first!\n" ); + return; + } + + CExpression *exp = active->GetExpression( index ); + if ( !exp ) + { + return; + } + + bool namechanged = false; + CExpressionParams params; + memset( ¶ms, 0, sizeof( params ) ); + + strcpy( params.m_szDialogTitle, "Edit Expression" ); + strcpy( params.m_szName, exp->name ); + strcpy( params.m_szDescription, exp->description ); + + if ( !ExpressionProperties( ¶ms ) ) + return; + + namechanged = stricmp( exp->name, params.m_szName ) ? true : false; + + if ( ( strlen( params.m_szName ) <= 0 ) || + !stricmp( params.m_szName, "unnamed" ) ) + { + Con_ErrorPrintf( "You must type in a valid name\n" ); + return; + } + + if ( ( strlen( params.m_szDescription ) <= 0 ) || + !stricmp( params.m_szDescription, "description" ) ) + { + Con_ErrorPrintf( "You must type in a valid description\n" ); + return; + } + + if ( namechanged ) + { + Con_Printf( "Deleting old bitmap %s\n", exp->GetBitmapFilename( models->GetActiveModelIndex() ) ); + + // Remove old bitmap + _unlink( exp->GetBitmapFilename( models->GetActiveModelIndex() ) ); + } + + strcpy( exp->name, params.m_szName ); + strcpy( exp->description, params.m_szDescription ); + + if ( namechanged ) + { + exp->CreateNewBitmap( models->GetActiveModelIndex() ); + } + + active->SetDirty( true ); + + g_pExpressionTrayTool->redraw(); +} + +void FlexPanel::NewExpression( void ) +{ + CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr(); + if ( !hdr ) + { + Con_ErrorPrintf( "Can't create new face pose, must load a model first!\n" ); + return; + } + + CExpClass *active = expressions->GetActiveClass(); + if ( !active ) + return; + + g_pExpressionTrayTool->Deselect(); + + CExpressionParams params; + memset( ¶ms, 0, sizeof( params ) ); + + strcpy( params.m_szDialogTitle, "Add Expression" ); + strcpy( params.m_szName, "" ); + strcpy( params.m_szDescription, "" ); + + if ( !ExpressionProperties( ¶ms ) ) + return; + + if ( ( strlen( params.m_szName ) <= 0 ) || + !stricmp( params.m_szName, "unnamed" ) ) + { + Con_ErrorPrintf( "You must type in a valid name\n" ); + return; + } + + if ( ( strlen( params.m_szDescription ) <= 0 ) || + !stricmp( params.m_szDescription, "description" ) ) + { + Con_ErrorPrintf( "You must type in a valid description\n" ); + return; + } + + float settings[ GLOBAL_STUDIO_FLEX_CONTROL_COUNT ]; + float weights[ GLOBAL_STUDIO_FLEX_CONTROL_COUNT ]; + memset( settings, 0, sizeof( settings ) ); + memset( weights, 0, sizeof( settings ) ); + for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); i++ ) + { + int j = hdr->pFlexcontroller( i )->localToGlobal; + + settings[ j ] = GetSlider( j ); + weights[ j ] = GetInfluence( j ); + } + + active->AddExpression( params.m_szName, params.m_szDescription, settings, weights, true, true ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool FlexPanel::PaintBackground( void ) +{ + redraw(); + return false; +} + +void FlexPanel::OnMenu() +{ + POINT pt; + pt.x = btnMenu->x(); + pt.y = btnMenu->y(); + pt.y -= 3 * btnMenu->h2(); + ScreenToClient( (HWND)getHandle(), &pt ); + + mxPopupMenu *pop = new mxPopupMenu(); + + pop->add( "Check All", IDC_FP_CHECK_ALL ); + pop->add( "Uncheck All", IDC_FP_UNCHECK_ALL ); + pop->add( "Invert Selection", IDC_FP_INVERT ); + + pop->popup( this, pt.x, pt.y ); +} |