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.
1092 lines
26 KiB
1092 lines
26 KiB
//========= 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 ); |
|
}
|
|
|