Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.
 
 
 
 
 
 

976 lines
22 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "ControlPanel.h"
#include "ViewerSettings.h"
#include "StudioModel.h"
#include "IStudioRender.h"
#include "MatSysWin.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mxtk/mx.h>
#include <mxtk/mxBmp.h>
#include "FlexPanel.h"
#include "mxExpressionTray.h"
#include "PhonemeEditor.h"
#include "hlfaceposer.h"
#include "expclass.h"
#include "mxExpressionTab.h"
#include "ExpressionTool.h"
#include "MDLViewer.h"
#include "choreowidgetdrawhelper.h"
#include "faceposer_models.h"
#include "ifaceposerworkspace.h"
#include "choreoview.h"
#include "GestureTool.h"
#include "RampTool.h"
#include "SceneRampTool.h"
#include "phonemeextractor/PhonemeExtractor.h"
#include "tier1/KeyValues.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern char g_appTitle[];
ControlPanel *g_pControlPanel = 0;
//-----------------------------------------------------------------------------
// Purpose: A simple subclass so we can paint the window background
//-----------------------------------------------------------------------------
class CControlPanelTabWindow : public mxWindow
{
public:
CControlPanelTabWindow( mxWindow *parent, int x, int y, int w, int h ) :
mxWindow( parent, x, y, w, h )
{
FacePoser_AddWindowStyle( this, WS_CLIPSIBLINGS | WS_CLIPCHILDREN );
};
virtual bool PaintBackground( void )
{
CChoreoWidgetDrawHelper drawHelper( this );
RECT rc;
drawHelper.GetClientRect( rc );
drawHelper.DrawFilledRect( GetSysColor( COLOR_BTNFACE ), rc );
return false;
}
};
ControlPanel::ControlPanel (mxWindow *parent)
: IFacePoserToolWindow( "ControlPanel", "Control Panel" ), mxWindow( parent, 0, 0, 0, 0 ), tab( 0 )
{
// create tabcontrol with subdialog windows
tab = new mxTab (this, 0, 0, 0, 0, IDC_TAB);
CControlPanelTabWindow *wRender = new CControlPanelTabWindow (this, 0, 0, 0, 0);
tab->add (wRender, "Render");
cRenderMode = new mxChoice (wRender, 5, 5, 100, 22, IDC_RENDERMODE);
cRenderMode->add ("Wireframe");
cRenderMode->add ("Flatshaded");
cRenderMode->add ("Smoothshaded");
cRenderMode->add ("Textured");
cRenderMode->select (3);
mxToolTip::add (cRenderMode, "Select Render Mode");
slModelGap = new mxSlider( wRender, 220, 5, 140, 20, IDC_MODELSPACING );
slModelGap->setRange( 0.0f, 64.0f, 256 );
slModelGap->setValue( 16 );
mxToolTip::add (slModelGap, "Select Model Spacing" );
new mxLabel (wRender, 220, 25, 140, 20, "Model Spacing");
cbAllWindowsDriveSpeech = new mxCheckBox( wRender, 220, 45, 140, 20, "All tools drive mouth", IDC_TOOLSDRIVEMOUTH );
cbAllWindowsDriveSpeech->setChecked( g_viewerSettings.faceposerToolsDriveMouth );
cbGround = new mxCheckBox (wRender, 110, 5, 100, 20, "Ground", IDC_GROUND);
cbGround->setEnabled( true );
cbMovement = new mxCheckBox (wRender, 110, 25, 100, 20, "Movement", IDC_MOVEMENT);
cbMovement->setEnabled( false );
cbBackground = new mxCheckBox (wRender, 110, 45, 100, 20, "Background", IDC_BACKGROUND);
cbBackground->setEnabled( false );
new mxCheckBox (wRender, 110, 65, 100, 20, "Hit Boxes", IDC_HITBOXES);
new mxCheckBox (wRender, 5, 65, 100, 20, "Bones", IDC_BONES);
mxCheckBox *cbAttachments = new mxCheckBox (wRender, 5, 45, 100, 20, "Attachments", IDC_ATTACHMENTS);
cbAttachments->setEnabled( false );
CControlPanelTabWindow *wSequence = new CControlPanelTabWindow (this, 0, 0, 0, 0);
tab->add (wSequence, "Sequence");
cSequence = new mxChoice (wSequence, 5, 5, 200, 22, IDC_SEQUENCE);
mxToolTip::add (cSequence, "Select Sequence");
slSpeedScale = new mxSlider (wSequence, 5, 32, 200, 18, IDC_SPEEDSCALE);
slSpeedScale->setRange (0.0, 5.0 );
slSpeedScale->setValue (0.0);
mxToolTip::add (slSpeedScale, "Speed Scale");
lSpeedScale = new mxLabel( wSequence, 5, 50, 200, 18 );
lSpeedScale->setLabel( "Speed scale" );
CControlPanelTabWindow *wBody = new CControlPanelTabWindow (this, 0, 0, 0, 0);
tab->add (wBody, "Body");
cBodypart = new mxChoice (wBody, 5, 5, 100, 22, IDC_BODYPART);
mxToolTip::add (cBodypart, "Choose a bodypart");
cSubmodel = new mxChoice (wBody, 110, 5, 100, 22, IDC_SUBMODEL);
mxToolTip::add (cSubmodel, "Choose a submodel of current bodypart");
cController = new mxChoice (wBody, 5, 30, 100, 22, IDC_CONTROLLER);
mxToolTip::add (cController, "Choose a bone controller");
slController = new mxSlider (wBody, 105, 32, 100, 18, IDC_CONTROLLERVALUE);
slController->setRange (0, 45);
mxToolTip::add (slController, "Change current bone controller value");
lModelInfo1 = new mxLabel (wBody, 220, 5, 120, 100, "No Model.");
lModelInfo2 = new mxLabel (wBody, 340, 5, 120, 100, "");
cSkin = new mxChoice (wBody, 5, 55, 100, 22, IDC_SKINS);
mxToolTip::add (cSkin, "Choose a skin family");
}
ControlPanel::~ControlPanel()
{
}
bool ControlPanel::CanClose( void )
{
workspacefiles->StartStoringFiles( IWorkspaceFiles::EXPRESSION );
for ( int i = 0 ; i < expressions->GetNumClasses(); i++ )
{
CExpClass *cl = expressions->GetClass( i );
if ( cl )
{
workspacefiles->StoreFile( IWorkspaceFiles::EXPRESSION, cl->GetFileName() );
}
}
workspacefiles->FinishStoringFiles( IWorkspaceFiles::EXPRESSION );
// Now close them all, or abort exit if user doesn't want to close any that have changed
return Closeall();
}
void ControlPanel::OnDelete()
{
}
void ControlPanel::PositionControls( int width, int height )
{
if ( tab )
{
tab->setBounds( 0, GetCaptionHeight(), width, height );
}
}
void ControlPanel::redraw()
{
if ( !ToolCanDraw() )
return;
CChoreoWidgetDrawHelper helper( this, GetSysColor( COLOR_BTNFACE ) );
HandleToolRedraw( helper );
BaseClass::redraw();
}
int
ControlPanel::handleEvent (mxEvent *event)
{
MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
int iret = 0;
if ( HandleToolEvent( event ) )
{
return iret;
}
switch ( event->event )
{
case mxEvent::Size:
{
PositionControls( event->width, event->height );
iret = 1;
}
break;
case mxEvent::Action:
{
iret = 1;
switch (event->action)
{
case IDC_TOOLSDRIVEMOUTH:
{
g_viewerSettings.faceposerToolsDriveMouth = ((mxCheckBox *)event->widget)->isChecked();
}
break;
case IDC_TAB:
{
g_viewerSettings.showTexture = (tab->getSelectedIndex() == 3);
}
break;
case IDC_RENDERMODE:
{
int index = cRenderMode->getSelectedIndex();
if (index >= 0)
{
setRenderMode (index);
}
}
break;
case IDC_GROUND:
setShowGround (((mxCheckBox *) event->widget)->isChecked());
break;
case IDC_MOVEMENT:
setShowMovement (((mxCheckBox *) event->widget)->isChecked());
break;
case IDC_BACKGROUND:
setShowBackground (((mxCheckBox *) event->widget)->isChecked());
break;
case IDC_HITBOXES:
g_viewerSettings.showHitBoxes = ((mxCheckBox *) event->widget)->isChecked();
break;
case IDC_PHYSICSMODEL:
g_viewerSettings.showPhysicsModel = ((mxCheckBox *) event->widget)->isChecked();
break;
case IDC_BONES:
g_viewerSettings.showBones = ((mxCheckBox *) event->widget)->isChecked();
break;
case IDC_ATTACHMENTS:
g_viewerSettings.showAttachments = ((mxCheckBox *) event->widget)->isChecked();
break;
case IDC_SEQUENCE:
{
int index = cSequence->getSelectedIndex();
if (index >= 0)
{
setSequence ( index );
}
}
break;
case IDC_SPEEDSCALE:
{
g_viewerSettings.speedScale = ((mxSlider *) event->widget)->getValue();
lSpeedScale->setLabel( va( "Speed scale %.2f", g_viewerSettings.speedScale ) );
}
break;
case IDC_PRIMARYBLEND:
{
setBlend( 0, ((mxSlider *) event->widget)->getValue() );
}
break;
case IDC_SECONDARYBLEND:
{
setBlend( 1, ((mxSlider *) event->widget)->getValue() );
}
break;
case IDC_BODYPART:
{
int index = cBodypart->getSelectedIndex();
if (index >= 0)
{
setBodypart (index);
}
}
break;
case IDC_SUBMODEL:
{
int index = cSubmodel->getSelectedIndex();
if (index >= 0)
{
setSubmodel (index);
}
}
break;
case IDC_CONTROLLER:
{
int index = cController->getSelectedIndex();
if (index >= 0)
setBoneController (index);
}
break;
case IDC_CONTROLLERVALUE:
{
int index = cController->getSelectedIndex();
if (index >= 0)
setBoneControllerValue (index, slController->getValue());
}
break;
case IDC_SKINS:
{
int index = cSkin->getSelectedIndex();
if (index >= 0)
{
models->GetActiveStudioModel()->SetSkin (index);
g_viewerSettings.skin = index;
g_pMatSysWindow->redraw();
}
}
break;
default:
iret = 0;
break;
}
}
}
return iret;
}
void ControlPanel::dumpModelInfo() { }
void ControlPanel::ChangeModel( const char *filename )
{
HCURSOR hPrevCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
// init all the selection tabs based on the current model
initSequenceChoices();
initBodypartChoices();
initBoneControllerChoices();
initSkinChoices();
setModelInfo();
SetCloseCaptionLanguageId( g_viewerSettings.cclanguageid, true );
g_viewerSettings.m_iEditAttachment = -1;
g_viewerSettings.enableIK = true;
g_viewerSettings.enableTargetIK = false;
setSequence( models->GetActiveStudioModel()->GetSequence() );
setSpeed( g_viewerSettings.speedScale );
mx_setcwd (mx_getpath (filename));
g_pFlexPanel->initFlexes();
// centerView();
// CenterOnFace();
IFacePoserToolWindow::ModelChanged();
CExpClass *cl = expressions->GetActiveClass();
if ( cl )
{
cl->SelectExpression( cl->GetSelectedExpression() );
}
SetSuffix( va( " - %s.mdl", models->GetActiveModelName() ) );
redraw();
SetCursor( hPrevCursor );
}
void
ControlPanel::setRenderMode (int mode)
{
g_viewerSettings.renderMode = mode;
g_pMatSysWindow->redraw();
}
void
ControlPanel::setHighlightBone( int index )
{
g_viewerSettings.highlightPhysicsBone = index;
}
void
ControlPanel::setShowGround (bool b)
{
g_viewerSettings.showGround = b;
cbGround->setChecked (b);
}
void
ControlPanel::setShowMovement (bool b)
{
g_viewerSettings.showMovement = b;
cbMovement->setChecked (b);
}
void
ControlPanel::setShowBackground (bool b)
{
g_viewerSettings.showBackground = b;
cbBackground->setChecked (b);
}
void
ControlPanel::initSequenceChoices()
{
CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
if (hdr)
{
cSequence->removeAll();
for (int i = 0; i < hdr->GetNumSeq(); i++)
{
cSequence->add (hdr->pSeqdesc(i).pszLabel());
}
cSequence->select (0);
}
}
void
ControlPanel::setSequence (int index)
{
cSequence->select (index);
models->GetActiveStudioModel()->SetSequence(index);
initPoseParameters( );
}
void
ControlPanel::setSpeed( float value )
{
g_viewerSettings.speedScale = value;
slSpeedScale->setValue( value );
}
void ControlPanel::setBlend(int index, float value )
{
models->GetActiveStudioModel()->SetPoseParameter( index, value );
}
void
ControlPanel::initBodypartChoices()
{
CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
if (hdr)
{
int i;
mstudiobodyparts_t *pbodyparts = hdr->pBodypart(0);
cBodypart->removeAll();
if (hdr->numbodyparts() > 0)
{
for (i = 0; i < hdr->numbodyparts(); i++)
cBodypart->add (pbodyparts[i].pszName());
cBodypart->select (0);
cSubmodel->removeAll();
for (i = 0; i < pbodyparts[0].nummodels; i++)
{
char str[64];
sprintf (str, "Submodel %d", i + 1);
cSubmodel->add (str);
}
cSubmodel->select (0);
}
}
}
void
ControlPanel::setBodypart (int index)
{
CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
if (hdr)
{
//cBodypart->setEn
cBodypart->select (index);
if (index < hdr->numbodyparts())
{
mstudiobodyparts_t *pbodyparts = hdr->pBodypart(0);
cSubmodel->removeAll();
for (int i = 0; i < pbodyparts[index].nummodels; i++)
{
char str[64];
sprintf (str, "Submodel %d", i + 1);
cSubmodel->add (str);
}
cSubmodel->select (0);
//models->GetActiveStudioModel()->SetBodygroup (index, 0);
}
}
}
void
ControlPanel::setSubmodel (int index)
{
models->GetActiveStudioModel()->SetBodygroup (cBodypart->getSelectedIndex(), index);
}
void
ControlPanel::initBoneControllerChoices()
{
CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
if (hdr)
{
cController->setEnabled (hdr->numbonecontrollers() > 0);
slController->setEnabled (hdr->numbonecontrollers() > 0);
cController->removeAll();
for (int i = 0; i < hdr->numbonecontrollers(); i++)
{
mstudiobonecontroller_t *pbonecontroller = hdr->pBonecontroller(i);
char str[32];
sprintf (str, "Controller %d", pbonecontroller->inputfield);
cController->add (str);
}
if (hdr->numbonecontrollers() > 0)
{
mstudiobonecontroller_t *pbonecontrollers = hdr->pBonecontroller(0);
cController->select (0);
slController->setRange (pbonecontrollers->start, pbonecontrollers->end);
slController->setValue (0);
}
}
}
void
ControlPanel::setBoneController (int index)
{
CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
if (hdr)
{
mstudiobonecontroller_t *pbonecontroller = hdr->pBonecontroller(index);
slController->setRange ( pbonecontroller->start, pbonecontroller->end);
slController->setValue (0);
}
}
void
ControlPanel::setBoneControllerValue (int index, float value)
{
CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
if (hdr)
{
mstudiobonecontroller_t *pbonecontrollers = hdr->pBonecontroller(index);
models->GetActiveStudioModel()->SetController (pbonecontrollers->inputfield, value);
}
}
void
ControlPanel::initPoseParameters()
{
CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
if (hdr)
{
for (int i = 0; i < hdr->GetNumPoseParameters(); i++)
{
setBlend( i, 0.0 );
}
}
}
void
ControlPanel::initSkinChoices()
{
CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
if (hdr)
{
cSkin->setEnabled (hdr->numskinfamilies() > 0);
cSkin->removeAll();
for (int i = 0; i < hdr->numskinfamilies(); i++)
{
char str[32];
sprintf (str, "Skin %d", i + 1);
cSkin->add (str);
}
cSkin->select (0);
models->GetActiveStudioModel()->SetSkin (0);
g_viewerSettings.skin = 0;
}
}
void
ControlPanel::setModelInfo()
{
static char str[2048];
CStudioHdr *hdr = models->GetActiveStudioModel()->GetStudioHdr();
if (!hdr)
return;
int hbcount = 0;
for ( int s = 0; s < hdr->numhitboxsets(); s++ )
{
hbcount += hdr->iHitboxCount( s );
}
sprintf (str,
"Bones: %d\n"
"Bone Controllers: %d\n"
"Hit Boxes: %d in %d sets\n"
"Sequences: %d\n",
hdr->numbones(),
hdr->numbonecontrollers(),
hbcount,
hdr->numhitboxsets(),
hdr->GetNumSeq()
);
lModelInfo1->setLabel (str);
sprintf (str,
"Textures: %d\n"
"Skin Families: %d\n"
"Bodyparts: %d\n"
"Attachments: %d\n",
hdr->numtextures(),
hdr->numskinfamilies(),
hdr->numbodyparts(),
hdr->GetNumAttachments());
lModelInfo2->setLabel (str);
}
void ControlPanel::CenterOnFace( void )
{
if ( !models->GetActiveStudioModel() )
return;
StudioModel *mdl = models->GetActiveStudioModel();
if ( !mdl )
return;
CStudioHdr *hdr = mdl->GetStudioHdr();
if ( !hdr )
return;
setSpeed( 1.0f );
int oldSeq = models->GetActiveStudioModel()->GetSequence();
int seq = models->GetActiveStudioModel()->LookupSequence( "idle_suble" );
if ( seq == -1 )
seq = 0;
if ( seq != oldSeq )
{
Con_Printf( "Centering changed model sequence # to %d\n", seq );
}
setSequence( seq );
initPoseParameters( );
mdl->m_angles.Init();
mdl->m_origin.Init();
Vector size;
VectorSubtract( hdr->hull_max(), hdr->hull_min(), size );
float eyeheight = hdr->hull_min().z + 0.9 * size.z;
if ( hdr->GetNumAttachments() > 0 )
{
for (int i = 0; i < hdr->GetNumAttachments(); i++)
{
const mstudioattachment_t &attachment = hdr->pAttachment( i );
int iBone = hdr->GetAttachmentBone( i );
if ( Q_stricmp( attachment.pszName(), "eyes" ) )
continue;
mstudiobone_t *bone = hdr->pBone( iBone );
if ( !bone )
continue;
matrix3x4_t boneToPose;
MatrixInvert( bone->poseToBone, boneToPose );
matrix3x4_t attachmentPoseToLocal;
ConcatTransforms( boneToPose, attachment.local, attachmentPoseToLocal );
Vector localSpaceEyePosition;
VectorITransform( vec3_origin, attachmentPoseToLocal, localSpaceEyePosition );
// Not sure why this must be negative?
eyeheight = -localSpaceEyePosition.z + hdr->hull_min().z;
break;
}
}
KeyValues *seqKeyValues = new KeyValues("");
if ( seqKeyValues->LoadFromBuffer( mdl->GetFileName( ), mdl->GetKeyValueText( seq ) ) )
{
// Do we have a build point section?
KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer");
if ( pkvAllFaceposer )
{
float flEyeheight = pkvAllFaceposer->GetFloat( "eye_height", -9999.0f );
if ( flEyeheight != -9999.0f )
{
eyeheight = flEyeheight;
}
}
}
seqKeyValues->deleteThis();
mdl->m_origin.x = size.z * .65f;
mdl->m_origin.z += eyeheight;
CUtlVector< StudioModel * > modellist;
modellist.AddToTail( models->GetActiveStudioModel() );
int i;
if ( models->CountVisibleModels() > 0 )
{
modellist.RemoveAll();
for ( i = 0; i < models->Count(); i++ )
{
if ( models->IsModelShownIn3DView( i ) )
{
modellist.AddToTail( models->GetStudioModel( i ) );
}
}
}
int modelcount = modellist.Count();
int countover2 = modelcount / 2;
int ydelta = GetModelGap();
int yoffset = -countover2 * ydelta;
for ( i = 0 ; i < modelcount; i++ )
{
if ( models->GetStudioHeader( i ) == hdr )
{
mdl->m_origin.y = -yoffset;
}
yoffset += ydelta;
}
g_pMatSysWindow->redraw();
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float ControlPanel::GetModelGap( void )
{
return slModelGap->getValue();
}
void
ControlPanel::centerView()
{
StudioModel *pModel = models->GetActiveStudioModel();
if ( !pModel )
return;
Vector min, max;
models->GetActiveStudioModel()->ExtractBbox (min, max);
float dx = max[0] - min[0];
float dy = max[1] - min[1];
float dz = max[2] - min[2];
float d = dx;
if (dy > d)
d = dy;
if (dz > d)
d = dz;
pModel->m_origin[0] = d * 1.0f;
pModel->m_origin[1] = 0;
pModel->m_origin[2] = min[2] + dz / 2;
pModel->m_angles[0] = 0.0f;
pModel->m_angles[1] = 0.0f;
pModel->m_angles[2] = 0.0f;
g_viewerSettings.lightrot.x = 0.f;
g_viewerSettings.lightrot.y = -180.0f;
g_viewerSettings.lightrot.z = 0.0f;
g_pMatSysWindow->redraw();
}
bool ControlPanel::Close()
{
int index = g_pExpressionClass->getSelectedIndex();
CExpClass *cl = expressions->GetClass( index );
if ( !cl )
return true;
return expressions->CloseClass( cl );
}
bool ControlPanel::Closeall()
{
bool retval = true;
while ( expressions->GetNumClasses() > 0 )
{
CExpClass *cl = expressions->GetClass( 0 );
if ( !cl )
break;
if ( !expressions->CloseClass( cl ) )
{
return false;
}
}
return retval;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ControlPanel::Copy( void )
{
g_pFlexPanel->CopyControllerSettings();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ControlPanel::Paste( void )
{
g_pFlexPanel->PasteControllerSettings();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ControlPanel::Undo( void )
{
CExpClass *active = expressions->GetActiveClass();
if ( !active )
return;
int index = active->GetSelectedExpression();
if ( index != -1 )
{
UndoExpression( index );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ControlPanel::Redo( void )
{
CExpClass *active = expressions->GetActiveClass();
if ( !active )
return;
int index = active->GetSelectedExpression();
if ( index != -1 )
{
RedoExpression( index );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ControlPanel::UndoExpression( int index )
{
if ( index == -1 )
return;
CExpClass *active = expressions->GetActiveClass();
if ( !active )
return;
CExpression *exp = active->GetExpression( index );
if ( exp )
{
exp->Undo();
// Show the updated data
active->SelectExpression( index );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ControlPanel::RedoExpression( int index )
{
if ( index == -1 )
return;
CExpClass *active = expressions->GetActiveClass();
if ( !active )
return;
CExpression *exp = active->GetExpression( index );
if ( exp )
{
exp->Redo();
// Show the updated data
active->SelectExpression( index );
}
}
void ControlPanel::DeleteExpression( int index )
{
CExpClass *active = expressions->GetActiveClass();
if ( !active )
return;
CExpression *exp = active->GetExpression( index );
if ( exp )
{
Con_Printf( "Deleting expression %s : %s\n", exp->name, exp->description );
g_pFlexPanel->DeleteExpression( index );
active->SelectExpression( max( 0, index - 1 ) );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : dt -
//-----------------------------------------------------------------------------
void ControlPanel::Think( float dt )
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool ControlPanel::AllToolsDriveSpeech( void )
{
return cbAllWindowsDriveSpeech->isChecked();
}