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
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();
|
|
}
|