summaryrefslogtreecommitdiff
path: root/utils/hlfaceposer/flexpanel.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/hlfaceposer/flexpanel.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'utils/hlfaceposer/flexpanel.cpp')
-rw-r--r--utils/hlfaceposer/flexpanel.cpp1092
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( &params, 0, sizeof( params ) );
+
+ strcpy( params.m_szDialogTitle, "Edit Expression" );
+ strcpy( params.m_szName, exp->name );
+ strcpy( params.m_szDescription, exp->description );
+
+ if ( !ExpressionProperties( &params ) )
+ 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( &params, 0, sizeof( params ) );
+
+ strcpy( params.m_szDialogTitle, "Add Expression" );
+ strcpy( params.m_szName, "" );
+ strcpy( params.m_szDescription, "" );
+
+ if ( !ExpressionProperties( &params ) )
+ 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 );
+}