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.
2811 lines
67 KiB
2811 lines
67 KiB
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//===========================================================================//
|
|
#include "cbase.h"
|
|
#include <direct.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <mxtk/mx.h>
|
|
#include <mxtk/mxTga.h>
|
|
#include <mxtk/mxEvent.h>
|
|
#include "mdlviewer.h"
|
|
#include "ViewerSettings.h"
|
|
#include "MatSysWin.h"
|
|
#include "ControlPanel.h"
|
|
#include "FlexPanel.h"
|
|
#include "StudioModel.h"
|
|
#include "mxExpressionTray.h"
|
|
#include "mxStatusWindow.h"
|
|
#include "ChoreoView.h"
|
|
#include "ifaceposersound.h"
|
|
#include "ifaceposerworkspace.h"
|
|
#include "expclass.h"
|
|
#include "PhonemeEditor.h"
|
|
#include "FileSystem.h"
|
|
#include "ExpressionTool.h"
|
|
#include "ControlPanel.h"
|
|
#include "choreowidgetdrawhelper.h"
|
|
#include "choreoviewcolors.h"
|
|
#include "tabwindow.h"
|
|
#include "faceposer_models.h"
|
|
#include "choiceproperties.h"
|
|
#include "choreoscene.h"
|
|
#include "choreoactor.h"
|
|
#include "tier1/strtools.h"
|
|
#include "InputProperties.h"
|
|
#include "GestureTool.h"
|
|
#include "SoundEmitterSystem/isoundemittersystembase.h"
|
|
#include "inputsystem/iinputsystem.h"
|
|
#include "RampTool.h"
|
|
#include "SceneRampTool.h"
|
|
#include "tier0/icommandline.h"
|
|
#include "phonemeextractor/PhonemeExtractor.h"
|
|
#include "animationbrowser.h"
|
|
#include "CloseCaptionTool.h"
|
|
#include "wavebrowser.h"
|
|
#include "vcdbrowser.h"
|
|
#include "ifilesystemopendialog.h"
|
|
#include <vgui/ILocalize.h>
|
|
#include <vgui/IVGui.h>
|
|
#include "appframework/appframework.h"
|
|
#include "icvar.h"
|
|
#include "vstdlib/cvar.h"
|
|
#include "istudiorender.h"
|
|
#include "materialsystem/imaterialsystem.h"
|
|
#include "vphysics_interface.h"
|
|
#include "Datacache/imdlcache.h"
|
|
#include "datacache/idatacache.h"
|
|
#include "filesystem_init.h"
|
|
#include "materialsystem/imaterialsystemhardwareconfig.h"
|
|
#include "tier1/strtools.h"
|
|
#include "appframework/tier3app.h"
|
|
#include "p4lib/ip4.h"
|
|
#include "tier2/p4helpers.h"
|
|
#include "ProgressDialog.h"
|
|
#include "scriplib.h"
|
|
#include "MessageBoxWithCheckBox.h"
|
|
#include "configmanager.h"
|
|
|
|
#define WINDOW_TAB_OFFSET 24
|
|
|
|
MDLViewer *g_MDLViewer = 0;
|
|
char g_appTitle[] = "Half-Life Face Poser";
|
|
static char recentFiles[8][256] = { "", "", "", "", "", "", "", "" };
|
|
|
|
using namespace vgui;
|
|
//-----------------------------------------------------------------------------
|
|
// Singleton interfaces
|
|
//-----------------------------------------------------------------------------
|
|
IPhysicsSurfaceProps *physprop;
|
|
IPhysicsCollision *physcollision;
|
|
IStudioDataCache *g_pStudioDataCache;
|
|
ISoundEmitterSystemBase *soundemitter = NULL;
|
|
CreateInterfaceFn g_Factory;
|
|
IFileSystem *g_pFileSystem = NULL;
|
|
|
|
bool g_bInError = false;
|
|
|
|
static char gamedir[MAX_PATH]; // full path to gamedir U:\main\game\ep2
|
|
static char gamedirsimple[MAX_PATH]; // just short name: ep2
|
|
|
|
// Filesystem dialog module wrappers.
|
|
CSysModule *g_pFSDialogModule = 0;
|
|
CreateInterfaceFn g_FSDialogFactory = 0;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// FIXME: Remove this crap (from cmdlib.cpp)
|
|
// We can't include cmdlib owing to appframework incompatibilities
|
|
//-----------------------------------------------------------------------------
|
|
void Q_mkdir( const char *path )
|
|
{
|
|
#if defined( _WIN32 ) || defined( WIN32 )
|
|
if (_mkdir (path) != -1)
|
|
return;
|
|
#else
|
|
if (mkdir (path, 0777) != -1)
|
|
return;
|
|
#endif
|
|
if (errno != EEXIST)
|
|
{
|
|
Error ("mkdir %s: %s",path, strerror(errno));
|
|
}
|
|
}
|
|
|
|
void CreatePath( const char *relative )
|
|
{
|
|
char fullpath[ 512 ];
|
|
Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", GetGameDirectory(), relative );
|
|
|
|
char *path = fullpath;
|
|
|
|
char *ofs, c;
|
|
|
|
if (path[1] == ':')
|
|
{
|
|
path += 2;
|
|
}
|
|
|
|
for (ofs = const_cast<char*>(path+1); *ofs ; ofs++)
|
|
{
|
|
c = *ofs;
|
|
if (c == '/' || c == '\\')
|
|
{
|
|
// create the directory, but not if it's actually a filename with a dot in it!!!
|
|
*ofs = 0;
|
|
if ( !Q_stristr( path, "." ) )
|
|
{
|
|
Q_mkdir (path);
|
|
}
|
|
*ofs = c;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// LoadFile
|
|
//-----------------------------------------------------------------------------
|
|
int LoadFile (const char *filename, void **bufferptr)
|
|
{
|
|
FileHandle_t f = filesystem->Open( filename, "rb" );
|
|
int length = filesystem->Size( f );
|
|
void *buffer = malloc (length+1);
|
|
((char *)buffer)[length] = 0;
|
|
if ( filesystem->Read (buffer, length, f) != (int)length )
|
|
{
|
|
Error ("File read failure");
|
|
}
|
|
filesystem->Close (f);
|
|
|
|
*bufferptr = buffer;
|
|
return length;
|
|
}
|
|
|
|
char *ExpandPath (char *path)
|
|
{
|
|
static char full[1024];
|
|
if (path[0] == '/' || path[0] == '\\' || path[1] == ':')
|
|
return path;
|
|
|
|
Q_snprintf (full, 1024, "%s%s", gamedir, path);
|
|
return full;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// FIXME: Move into appsystem framework
|
|
//-----------------------------------------------------------------------------
|
|
void LoadFileSystemDialogModule()
|
|
{
|
|
Assert( !g_pFSDialogModule );
|
|
|
|
// Load the module with the file system open dialog.
|
|
const char *pDLLName = "FileSystemOpenDialog.dll";
|
|
g_pFSDialogModule = Sys_LoadModule( pDLLName );
|
|
if ( g_pFSDialogModule )
|
|
{
|
|
g_FSDialogFactory = Sys_GetFactory( g_pFSDialogModule );
|
|
}
|
|
|
|
if ( !g_pFSDialogModule || !g_FSDialogFactory )
|
|
{
|
|
if ( g_pFSDialogModule )
|
|
{
|
|
Sys_UnloadModule( g_pFSDialogModule );
|
|
g_pFSDialogModule = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void UnloadFileSystemDialogModule()
|
|
{
|
|
if ( g_pFSDialogModule )
|
|
{
|
|
Sys_UnloadModule( g_pFSDialogModule );
|
|
g_pFSDialogModule = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
MDLViewer::initRecentFiles ()
|
|
{
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
if (strlen (recentFiles[i]))
|
|
{
|
|
mb->modify (IDC_FILE_RECENTFILES1 + i, IDC_FILE_RECENTFILES1 + i, recentFiles[i]);
|
|
}
|
|
else
|
|
{
|
|
mb->modify (IDC_FILE_RECENTFILES1 + i, IDC_FILE_RECENTFILES1 + i, "(empty)");
|
|
mb->setEnabled (IDC_FILE_RECENTFILES1 + i, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#define RECENTFILESPATH "/hlfaceposer.rf"
|
|
void
|
|
MDLViewer::loadRecentFiles ()
|
|
{
|
|
char path[256];
|
|
strcpy (path, mx::getApplicationPath ());
|
|
strcat (path, RECENTFILESPATH);
|
|
FILE *file = fopen (path, "rb");
|
|
if (file)
|
|
{
|
|
fread (recentFiles, sizeof recentFiles, 1, file);
|
|
fclose (file);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void
|
|
MDLViewer::saveRecentFiles ()
|
|
{
|
|
char path[256];
|
|
|
|
strcpy (path, mx::getApplicationPath ());
|
|
strcat (path, RECENTFILESPATH);
|
|
|
|
FILE *file = fopen (path, "wb");
|
|
if (file)
|
|
{
|
|
fwrite (recentFiles, sizeof recentFiles, 1, file);
|
|
fclose (file);
|
|
}
|
|
}
|
|
|
|
bool MDLViewer::AreSoundScriptsDirty()
|
|
{
|
|
// Save any changed sound script files
|
|
int c = soundemitter->GetNumSoundScripts();
|
|
for ( int i = 0; i < c; i++ )
|
|
{
|
|
if ( soundemitter->IsSoundScriptDirty( i ) )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool MDLViewer::CanClose()
|
|
{
|
|
Con_Printf( "Checking for vcd changes...\n" );
|
|
|
|
if ( m_vecDirtyVCDs.Count() > 0 )
|
|
{
|
|
CMessageBoxWithCheckBoxParams params;
|
|
Q_memset( ¶ms, 0, sizeof( params ) );
|
|
Q_strncpy( params.m_szDialogTitle, "Scenes Image", sizeof( params.m_szDialogTitle ) );
|
|
Q_strncpy( params.m_szPrompt, "Update scenes.image?", sizeof( params.m_szPrompt ) );
|
|
Q_strncpy( params.m_szCheckBoxText, "Rebuild full .image", sizeof( params.m_szCheckBoxText ) );
|
|
params.m_bChecked = false;
|
|
|
|
// FIXME: Needs a "rebuild all" checkbox
|
|
if ( !MessageBoxWithCheckBox( ¶ms ) )
|
|
return false;
|
|
|
|
if ( params.m_bChecked )
|
|
{
|
|
OnRebuildScenesImage();
|
|
}
|
|
else
|
|
{
|
|
OnUpdateScenesImage();
|
|
}
|
|
}
|
|
|
|
Con_Printf( "Checking for sound script changes...\n" );
|
|
|
|
// Save any changed sound script files
|
|
int c = soundemitter->GetNumSoundScripts();
|
|
for ( int i = 0; i < c; i++ )
|
|
{
|
|
if ( !soundemitter->IsSoundScriptDirty( i ) )
|
|
continue;
|
|
|
|
char const *scriptname = soundemitter->GetSoundScriptName( i );
|
|
if ( !scriptname )
|
|
continue;
|
|
|
|
if ( !filesystem->FileExists( scriptname ) ||
|
|
!filesystem->IsFileWritable( scriptname ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
int retval = mxMessageBox( NULL, va( "Save changes to sound script '%s'?", scriptname ), g_appTitle, MX_MB_YESNOCANCEL );
|
|
if ( retval == 2 )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( retval == 0 )
|
|
{
|
|
soundemitter->SaveChangesToSoundScript( i );
|
|
}
|
|
}
|
|
|
|
SaveWindowPositions();
|
|
|
|
models->SaveModelList();
|
|
models->CloseAllModels();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool MDLViewer::Closing( void )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
#define IDC_GRIDSETTINGS_FPS 1001
|
|
#define IDC_GRIDSETTINGS_SNAP 1002
|
|
|
|
class CFlatButton : public mxButton
|
|
{
|
|
public:
|
|
CFlatButton( mxWindow *parent, int id )
|
|
: mxButton( parent, 0, 0, 0, 0, "", id )
|
|
{
|
|
HWND wnd = (HWND)getHandle();
|
|
DWORD exstyle = GetWindowLong( wnd, GWL_EXSTYLE );
|
|
exstyle |= WS_EX_CLIENTEDGE;
|
|
SetWindowLong( wnd, GWL_EXSTYLE, exstyle );
|
|
|
|
DWORD style = GetWindowLong( wnd, GWL_STYLE );
|
|
style &= ~WS_BORDER;
|
|
SetWindowLong( wnd, GWL_STYLE, style );
|
|
|
|
}
|
|
};
|
|
|
|
class CMDLViewerGridSettings : public mxWindow
|
|
{
|
|
public:
|
|
typedef mxWindow BaseClass;
|
|
|
|
CMDLViewerGridSettings( mxWindow *parent, int x, int y, int w, int h ) :
|
|
mxWindow( parent, x, y, w, h )
|
|
{
|
|
FacePoser_AddWindowStyle( this, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
|
|
m_btnFPS = new CFlatButton( this, IDC_GRIDSETTINGS_FPS );
|
|
m_btnGridSnap = new CFlatButton( this, IDC_GRIDSETTINGS_SNAP );
|
|
|
|
}
|
|
|
|
void Init( void )
|
|
{
|
|
if ( g_pChoreoView )
|
|
{
|
|
CChoreoScene *scene = g_pChoreoView->GetScene();
|
|
if ( scene )
|
|
{
|
|
char sz[ 256 ];
|
|
Q_snprintf( sz, sizeof( sz ), "%i fps", scene->GetSceneFPS() );
|
|
m_btnFPS->setLabel( sz );
|
|
|
|
Q_snprintf( sz, sizeof( sz ), "snap: %s", scene->IsUsingFrameSnap() ? "on" : "off" );
|
|
m_btnGridSnap->setLabel( sz );
|
|
|
|
m_btnFPS->setVisible( true );
|
|
m_btnGridSnap->setVisible( true );
|
|
return;
|
|
}
|
|
}
|
|
|
|
m_btnFPS->setVisible( false );
|
|
m_btnGridSnap->setVisible( false );
|
|
}
|
|
|
|
virtual int handleEvent( mxEvent *event )
|
|
{
|
|
int iret = 0;
|
|
switch ( event->event )
|
|
{
|
|
default:
|
|
break;
|
|
case mxEvent::Size:
|
|
{
|
|
int leftedge = w2() * 0.45f;
|
|
m_btnFPS->setBounds( 0, 0, leftedge, h2() );
|
|
m_btnGridSnap->setBounds( leftedge, 0, w2() - leftedge, h2() );
|
|
iret = 1;
|
|
}
|
|
break;
|
|
case mxEvent::Action:
|
|
{
|
|
iret = 1;
|
|
switch ( event->action )
|
|
{
|
|
default:
|
|
iret = 0;
|
|
break;
|
|
case IDC_GRIDSETTINGS_FPS:
|
|
{
|
|
if ( g_pChoreoView )
|
|
{
|
|
CChoreoScene *scene = g_pChoreoView->GetScene();
|
|
if ( scene )
|
|
{
|
|
int currentFPS = scene->GetSceneFPS();
|
|
|
|
CInputParams params;
|
|
memset( ¶ms, 0, sizeof( params ) );
|
|
|
|
strcpy( params.m_szDialogTitle, "Change FPS" );
|
|
|
|
Q_snprintf( params.m_szInputText, sizeof( params.m_szInputText ),
|
|
"%i", currentFPS );
|
|
|
|
strcpy( params.m_szPrompt, "Current FPS:" );
|
|
|
|
if ( InputProperties( ¶ms ) )
|
|
{
|
|
int newFPS = atoi( params.m_szInputText );
|
|
|
|
if ( ( newFPS > 0 ) && ( newFPS != currentFPS ) )
|
|
{
|
|
g_pChoreoView->SetDirty( true );
|
|
g_pChoreoView->PushUndo( "Change Scene FPS" );
|
|
scene->SetSceneFPS( newFPS );
|
|
g_pChoreoView->PushRedo( "Change Scene FPS" );
|
|
Init();
|
|
|
|
Con_Printf( "FPS changed to %i\n", newFPS );
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case IDC_GRIDSETTINGS_SNAP:
|
|
{
|
|
if ( g_pChoreoView )
|
|
{
|
|
CChoreoScene *scene = g_pChoreoView->GetScene();
|
|
if ( scene )
|
|
{
|
|
g_pChoreoView->SetDirty( true );
|
|
g_pChoreoView->PushUndo( "Change Snap Frame" );
|
|
|
|
scene->SetUsingFrameSnap( !scene->IsUsingFrameSnap() );
|
|
|
|
g_pChoreoView->PushRedo( "Change Snap Frame" );
|
|
|
|
Init();
|
|
|
|
Con_Printf( "Time frame snapping: %s\n",
|
|
scene->IsUsingFrameSnap() ? "on" : "off" );
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return iret;
|
|
}
|
|
|
|
bool PaintBackground( void )
|
|
{
|
|
CChoreoWidgetDrawHelper drawHelper( this );
|
|
RECT rc;
|
|
drawHelper.GetClientRect( rc );
|
|
drawHelper.DrawFilledRect( RGBToColor( GetSysColor( COLOR_BTNFACE ) ), rc );
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
|
|
CFlatButton *m_btnFPS;
|
|
CFlatButton *m_btnGridSnap;
|
|
};
|
|
|
|
|
|
#define IDC_MODELTAB_LOAD 1000
|
|
#define IDC_MODELTAB_CLOSE 1001
|
|
#define IDC_MODELTAB_CLOSEALL 1002
|
|
#define IDC_MODELTAB_CENTERONFACE 1003
|
|
#define IDC_MODELTAB_ASSOCIATEACTOR 1004
|
|
#define IDC_MODELTAB_TOGGLE3DVIEW 1005
|
|
#define IDC_MODELTAB_SHOWALL 1006
|
|
#define IDC_MODELTAB_HIDEALL 1007
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
class CMDLViewerModelTab : public CTabWindow
|
|
{
|
|
public:
|
|
typedef CTabWindow BaseClass;
|
|
|
|
CMDLViewerModelTab( mxWindow *parent, int x, int y, int w, int h, int id = 0, int style = 0 ) :
|
|
CTabWindow( parent, x, y, w, h, id, style )
|
|
{
|
|
SetInverted( true );
|
|
}
|
|
|
|
virtual void ShowRightClickMenu( int mx, int my )
|
|
{
|
|
mxPopupMenu *pop = new mxPopupMenu();
|
|
Assert( pop );
|
|
|
|
char const *current = "";
|
|
char const *filename = "";
|
|
int idx = getSelectedIndex();
|
|
if ( idx >= 0 )
|
|
{
|
|
current = models->GetModelName( idx );
|
|
filename = models->GetModelFileName( idx );
|
|
}
|
|
|
|
if ( models->Count() < MAX_FP_MODELS )
|
|
{
|
|
pop->add( "Load Model...", IDC_MODELTAB_LOAD );
|
|
}
|
|
if ( idx >= 0 )
|
|
{
|
|
pop->add( va( "Close '%s'", current ), IDC_MODELTAB_CLOSE );
|
|
}
|
|
if ( models->Count() > 0 )
|
|
{
|
|
pop->add( "Close All", IDC_MODELTAB_CLOSEALL );
|
|
}
|
|
if ( idx >= 0 )
|
|
{
|
|
pop->addSeparator();
|
|
pop->add( va( "Center %s's face", current ), IDC_MODELTAB_CENTERONFACE );
|
|
|
|
CChoreoScene *scene = g_pChoreoView->GetScene();
|
|
if ( scene )
|
|
{
|
|
// See if there is already an actor with this model associated
|
|
int c = scene->GetNumActors();
|
|
bool hasassoc = false;
|
|
for ( int i = 0; i < c; i++ )
|
|
{
|
|
CChoreoActor *a = scene->GetActor( i );
|
|
Assert( a );
|
|
|
|
if ( stricmp( a->GetFacePoserModelName(), filename ) )
|
|
continue;
|
|
hasassoc = true;
|
|
break;
|
|
}
|
|
|
|
if ( hasassoc )
|
|
{
|
|
pop->add( va( "Change associated actor for %s", current ), IDC_MODELTAB_ASSOCIATEACTOR );
|
|
}
|
|
else
|
|
{
|
|
pop->add( va( "Associate actor to %s", current ), IDC_MODELTAB_ASSOCIATEACTOR );
|
|
}
|
|
}
|
|
|
|
pop->addSeparator();
|
|
|
|
bool visible = models->IsModelShownIn3DView( idx );
|
|
if ( visible )
|
|
{
|
|
pop->add( va( "Remove %s from 3D View", current ), IDC_MODELTAB_TOGGLE3DVIEW );
|
|
}
|
|
else
|
|
{
|
|
pop->add( va( "Show %s in 3D View", current ), IDC_MODELTAB_TOGGLE3DVIEW );
|
|
}
|
|
}
|
|
if ( models->Count() > 0 )
|
|
{
|
|
pop->addSeparator();
|
|
pop->add( "Show All", IDC_MODELTAB_SHOWALL );
|
|
pop->add( "Hide All", IDC_MODELTAB_HIDEALL );
|
|
}
|
|
|
|
// Convert click position
|
|
POINT pt;
|
|
pt.x = mx;
|
|
pt.y = my;
|
|
|
|
// Convert coordinate space
|
|
pop->popup( this, pt.x, pt.y );
|
|
}
|
|
|
|
virtual int handleEvent( mxEvent *event )
|
|
{
|
|
int iret = 0;
|
|
switch ( event->event )
|
|
{
|
|
default:
|
|
break;
|
|
case mxEvent::Action:
|
|
{
|
|
iret = 1;
|
|
switch ( event->action )
|
|
{
|
|
default:
|
|
iret = 0;
|
|
break;
|
|
case IDC_MODELTAB_SHOWALL:
|
|
case IDC_MODELTAB_HIDEALL:
|
|
{
|
|
bool show = ( event->action == IDC_MODELTAB_SHOWALL ) ? true : false;
|
|
int c = models->Count();
|
|
for ( int i = 0; i < c ; i++ )
|
|
{
|
|
models->ShowModelIn3DView( i, show );
|
|
}
|
|
}
|
|
break;
|
|
case IDC_MODELTAB_LOAD:
|
|
{
|
|
if ( filesystem->IsSteam() )
|
|
{
|
|
g_MDLViewer->LoadModel_Steam();
|
|
}
|
|
else
|
|
{
|
|
char modelfile[ 512 ];
|
|
if ( FacePoser_ShowOpenFileNameDialog( modelfile, sizeof( modelfile ), "models", "*.mdl" ) )
|
|
{
|
|
g_MDLViewer->LoadModelFile( modelfile );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case IDC_MODELTAB_CLOSE:
|
|
{
|
|
int idx = getSelectedIndex();
|
|
if ( idx >= 0 )
|
|
{
|
|
models->FreeModel( idx );
|
|
}
|
|
}
|
|
break;
|
|
case IDC_MODELTAB_CLOSEALL:
|
|
{
|
|
models->CloseAllModels();
|
|
}
|
|
break;
|
|
case IDC_MODELTAB_CENTERONFACE:
|
|
{
|
|
g_pControlPanel->CenterOnFace();
|
|
}
|
|
break;
|
|
case IDC_MODELTAB_TOGGLE3DVIEW:
|
|
{
|
|
int idx = getSelectedIndex();
|
|
if ( idx >= 0 )
|
|
{
|
|
bool visible = models->IsModelShownIn3DView( idx );
|
|
models->ShowModelIn3DView( idx, !visible );
|
|
}
|
|
}
|
|
break;
|
|
case IDC_MODELTAB_ASSOCIATEACTOR:
|
|
{
|
|
int idx = getSelectedIndex();
|
|
if ( idx >= 0 )
|
|
{
|
|
char const *modelname = models->GetModelFileName( idx );
|
|
|
|
CChoreoScene *scene = g_pChoreoView->GetScene();
|
|
if ( scene )
|
|
{
|
|
CChoiceParams params;
|
|
strcpy( params.m_szDialogTitle, "Associate Actor" );
|
|
|
|
params.m_bPositionDialog = false;
|
|
params.m_nLeft = 0;
|
|
params.m_nTop = 0;
|
|
strcpy( params.m_szPrompt, "Choose actor:" );
|
|
|
|
params.m_Choices.RemoveAll();
|
|
|
|
params.m_nSelected = -1;
|
|
int oldsel = -1;
|
|
|
|
int c = scene->GetNumActors();
|
|
ChoiceText text;
|
|
for ( int i = 0; i < c; i++ )
|
|
{
|
|
CChoreoActor *a = scene->GetActor( i );
|
|
Assert( a );
|
|
|
|
|
|
strcpy( text.choice, a->GetName() );
|
|
|
|
if ( !stricmp( a->GetFacePoserModelName(), modelname ) )
|
|
{
|
|
params.m_nSelected = i;
|
|
oldsel = -1;
|
|
}
|
|
|
|
params.m_Choices.AddToTail( text );
|
|
}
|
|
|
|
if ( ChoiceProperties( ¶ms ) &&
|
|
params.m_nSelected != oldsel )
|
|
{
|
|
|
|
// Chose something new...
|
|
CChoreoActor *a = scene->GetActor( params.m_nSelected );
|
|
|
|
g_pChoreoView->AssociateModelToActor( a, idx );
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
if ( iret )
|
|
return iret;
|
|
return BaseClass::handleEvent( event );
|
|
}
|
|
|
|
|
|
void HandleModelSelect( void )
|
|
{
|
|
int idx = getSelectedIndex();
|
|
if ( idx < 0 )
|
|
return;
|
|
|
|
// FIXME: Do any necessary window resetting here!!!
|
|
g_pControlPanel->ChangeModel( models->GetModelFileName( idx ) );
|
|
}
|
|
|
|
void Init( void )
|
|
{
|
|
removeAll();
|
|
|
|
int c = models->Count();
|
|
int i;
|
|
for ( i = 0; i < c ; i++ )
|
|
{
|
|
char const *name = models->GetModelName( i );
|
|
|
|
// Strip it down to the base name
|
|
char cleanname[ 256 ];
|
|
Q_FileBase( name, cleanname, sizeof( cleanname ) );
|
|
|
|
add( cleanname );
|
|
}
|
|
}
|
|
};
|
|
|
|
#define IDC_TOOL_TOGGLEVISIBILITY 1000
|
|
#define IDC_TOOL_TOGGLELOCK 1001
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
class CMDLViewerWindowTab : public CTabWindow
|
|
{
|
|
public:
|
|
typedef CTabWindow BaseClass;
|
|
|
|
CMDLViewerWindowTab( mxWindow *parent, int x, int y, int w, int h, int id = 0, int style = 0 ) :
|
|
CTabWindow( parent, x, y, w, h, id, style )
|
|
{
|
|
SetInverted( true );
|
|
|
|
m_nLastSelected = -1;
|
|
m_flLastSelectedTime = -1;
|
|
}
|
|
|
|
virtual void ShowRightClickMenu( int mx, int my )
|
|
{
|
|
IFacePoserToolWindow *tool = GetSelectedTool();
|
|
if ( !tool )
|
|
return;
|
|
|
|
mxWindow *toolw = tool->GetMxWindow();
|
|
if ( !toolw )
|
|
return;
|
|
|
|
mxPopupMenu *pop = new mxPopupMenu();
|
|
Assert( pop );
|
|
|
|
bool isVisible = toolw->isVisible();
|
|
bool isLocked = tool->IsLocked();
|
|
|
|
pop->add( isVisible ? "Hide" : "Show", IDC_TOOL_TOGGLEVISIBILITY );
|
|
pop->add( isLocked ? "Unlock" : "Lock", IDC_TOOL_TOGGLELOCK );
|
|
|
|
// Convert click position
|
|
POINT pt;
|
|
pt.x = mx;
|
|
pt.y = my;
|
|
|
|
/*
|
|
ClientToScreen( (HWND)getHandle(), &pt );
|
|
ScreenToClient( (HWND)g_MDLViewer->getHandle(), &pt );
|
|
*/
|
|
|
|
// Convert coordinate space
|
|
pop->popup( this, pt.x, pt.y );
|
|
}
|
|
|
|
virtual int handleEvent( mxEvent *event )
|
|
{
|
|
int iret = 0;
|
|
switch ( event->event )
|
|
{
|
|
case mxEvent::Action:
|
|
{
|
|
iret = 1;
|
|
switch ( event->action )
|
|
{
|
|
default:
|
|
iret = 0;
|
|
break;
|
|
case IDC_TOOL_TOGGLEVISIBILITY:
|
|
{
|
|
IFacePoserToolWindow *tool = GetSelectedTool();
|
|
if ( tool )
|
|
{
|
|
mxWindow *toolw = tool->GetMxWindow();
|
|
if ( toolw )
|
|
{
|
|
toolw->setVisible( !toolw->isVisible() );
|
|
g_MDLViewer->UpdateWindowMenu();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case IDC_TOOL_TOGGLELOCK:
|
|
{
|
|
IFacePoserToolWindow *tool = GetSelectedTool();
|
|
if ( tool )
|
|
{
|
|
tool->ToggleLockedState();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if ( iret )
|
|
return iret;
|
|
return BaseClass::handleEvent( event );
|
|
}
|
|
|
|
void Init( void )
|
|
{
|
|
int c = IFacePoserToolWindow::GetToolCount();
|
|
int i;
|
|
for ( i = 0; i < c ; i++ )
|
|
{
|
|
IFacePoserToolWindow *tool = IFacePoserToolWindow::GetTool( i );
|
|
add( tool->GetDisplayNameRoot() );
|
|
}
|
|
}
|
|
|
|
#define WINDOW_DOUBLECLICK_TIME 0.4
|
|
|
|
void HandleWindowSelect( void )
|
|
{
|
|
extern double realtime;
|
|
IFacePoserToolWindow *tool = GetSelectedTool();
|
|
if ( !tool )
|
|
return;
|
|
|
|
bool doubleclicked = false;
|
|
|
|
double curtime = realtime;
|
|
int clickedItem = getSelectedIndex();
|
|
|
|
if ( clickedItem == m_nLastSelected )
|
|
{
|
|
if ( curtime < m_flLastSelectedTime + WINDOW_DOUBLECLICK_TIME )
|
|
{
|
|
doubleclicked = true;
|
|
}
|
|
}
|
|
|
|
m_flLastSelectedTime = curtime;
|
|
m_nLastSelected = clickedItem;
|
|
|
|
mxWindow *toolw = tool->GetMxWindow();
|
|
if ( !toolw )
|
|
return;
|
|
|
|
if ( doubleclicked )
|
|
{
|
|
toolw->setVisible( !toolw->isVisible() );
|
|
m_flLastSelectedTime = -1;
|
|
}
|
|
|
|
if ( !toolw->isVisible() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Move window to front
|
|
HWND wnd = (HWND)tool->GetMxWindow()->getHandle();
|
|
SetFocus( wnd );
|
|
SetWindowPos( wnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
|
|
}
|
|
|
|
private:
|
|
|
|
IFacePoserToolWindow *GetSelectedTool()
|
|
{
|
|
int idx = getSelectedIndex();
|
|
int c = IFacePoserToolWindow::GetToolCount();
|
|
|
|
if ( idx < 0 || idx >= c )
|
|
return NULL;
|
|
|
|
IFacePoserToolWindow *tool = IFacePoserToolWindow::GetTool( idx );
|
|
return tool;
|
|
}
|
|
|
|
// HACKY double click handler
|
|
int m_nLastSelected;
|
|
double m_flLastSelectedTime;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: The workspace is the parent of all of the tool windows
|
|
//-----------------------------------------------------------------------------
|
|
class CMDLViewerWorkspace : public mxWindow
|
|
{
|
|
public:
|
|
CMDLViewerWorkspace( mxWindow *parent, int x, int y, int w, int h, const char *label = 0, int style = 0)
|
|
: mxWindow( parent, x, y, w, h, label, style )
|
|
{
|
|
FacePoser_AddWindowStyle( this, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Output : Returns true on success, false on failure.
|
|
//-----------------------------------------------------------------------------
|
|
bool PaintBackground( void )
|
|
{
|
|
CChoreoWidgetDrawHelper drawHelper( this );
|
|
RECT rc;
|
|
drawHelper.GetClientRect( rc );
|
|
drawHelper.DrawFilledRect( RGBToColor( GetSysColor( COLOR_APPWORKSPACE ) ), rc );
|
|
return false;
|
|
}
|
|
};
|
|
|
|
void MDLViewer::LoadPosition( void )
|
|
{
|
|
bool visible;
|
|
bool locked;
|
|
bool zoomed;
|
|
int x, y, w, h;
|
|
|
|
FacePoser_LoadWindowPositions( "MDLViewer", visible, x, y, w, h, locked, zoomed );
|
|
|
|
if ( w == 0 || h == 0 )
|
|
{
|
|
zoomed = true;
|
|
visible = true;
|
|
}
|
|
|
|
setBounds( x, y, w, h );
|
|
if ( zoomed )
|
|
{
|
|
ShowWindow( (HWND)getHandle(), SW_SHOWMAXIMIZED );
|
|
}
|
|
else
|
|
{
|
|
setVisible( visible );
|
|
}
|
|
}
|
|
|
|
void MDLViewer::SavePosition( void )
|
|
{
|
|
bool visible;
|
|
int xpos, ypos, width, height;
|
|
|
|
visible = isVisible();
|
|
xpos = x();
|
|
ypos = y();
|
|
width = w();
|
|
height = h();
|
|
|
|
// xpos and ypos are screen space
|
|
POINT pt;
|
|
pt.x = xpos;
|
|
pt.y = ypos;
|
|
|
|
// Convert from screen space to relative to client area of parent window so
|
|
// the setBounds == MoveWindow call will offset to the same location
|
|
if ( getParent() )
|
|
{
|
|
ScreenToClient( (HWND)getParent()->getHandle(), &pt );
|
|
xpos = (short)pt.x;
|
|
ypos = (short)pt.y;
|
|
}
|
|
|
|
bool zoomed = IsZoomed( (HWND)getHandle() ) ? true : false;
|
|
|
|
bool iconic = IsIconic( (HWND)getHandle() ) ? true : false;
|
|
|
|
// Don't reset values if it's minimized during shutdown
|
|
if ( iconic )
|
|
return;
|
|
|
|
FacePoser_SaveWindowPositions( "MDLViewer", visible, xpos, ypos, width, height, false, zoomed );
|
|
}
|
|
|
|
MDLViewer::MDLViewer () :
|
|
mxWindow (0, 0, 0, 0, 0, g_appTitle, mxWindow::Normal),
|
|
menuCloseCaptionLanguages(0),
|
|
m_bOldSoundScriptsDirty( -1 ),
|
|
m_bAlwaysUpdate( true )
|
|
{
|
|
int i;
|
|
|
|
g_MDLViewer = this;
|
|
|
|
FacePoser_MakeToolWindow( this, false );
|
|
|
|
workspace = new CMDLViewerWorkspace( this, 0, 0, 500, 500, "" );
|
|
windowtab = new CMDLViewerWindowTab( this, 0, 500, 500, 20, IDC_WINDOW_TAB );
|
|
modeltab = new CMDLViewerModelTab( this, 500, 500, 200, 20, IDC_MODEL_TAB );
|
|
gridsettings = new CMDLViewerGridSettings( this, 0, 500, 500, 20 );
|
|
modeltab->SetRightJustify( true );
|
|
|
|
g_pStatusWindow = new mxStatusWindow( workspace, 0, 0, 1024, 150, "" );
|
|
g_pStatusWindow->setVisible( true );
|
|
|
|
InitViewerSettings( "faceposer" );
|
|
g_viewerSettings.speechapiindex = SPEECH_API_LIPSINC;
|
|
g_viewerSettings.m_iEditAttachment = -1;
|
|
|
|
LoadViewerRootSettings( );
|
|
|
|
LoadPosition();
|
|
|
|
g_pStatusWindow->setBounds( 0, h2() - 150, w2(), 150 );
|
|
|
|
Con_Printf( "MDLViewer started\n" );
|
|
|
|
Con_Printf( "Creating menu bar\n" );
|
|
|
|
// create menu stuff
|
|
mb = new mxMenuBar (this);
|
|
menuFile = new mxMenu ();
|
|
menuOptions = new mxMenu ();
|
|
menuWindow = new mxMenu ();
|
|
menuHelp = new mxMenu ();
|
|
menuEdit = new mxMenu ();
|
|
menuExpressions = new mxMenu();
|
|
menuChoreography = new mxMenu();
|
|
menuFoundry = new mxMenu();
|
|
|
|
mb->addMenu ("File", menuFile);
|
|
//mb->addMenu( "Edit", menuEdit );
|
|
mb->addMenu ("Options", menuOptions);
|
|
mb->addMenu ( "Expression", menuExpressions );
|
|
mb->addMenu ( "Choreography", menuChoreography );
|
|
|
|
// Don't show Foundry mode in the SDK
|
|
if ( CGameConfigManager::IsSDKDeployment() == false )
|
|
{
|
|
mb->addMenu ("Foundry", menuFoundry);
|
|
}
|
|
|
|
mb->addMenu ("Window", menuWindow);
|
|
mb->addMenu ("Help", menuHelp);
|
|
|
|
mxMenu *menuRecentFiles = new mxMenu ();
|
|
menuRecentFiles->add ("(empty)", IDC_FILE_RECENTFILES1);
|
|
menuRecentFiles->add ("(empty)", IDC_FILE_RECENTFILES2);
|
|
menuRecentFiles->add ("(empty)", IDC_FILE_RECENTFILES3);
|
|
menuRecentFiles->add ("(empty)", IDC_FILE_RECENTFILES4);
|
|
|
|
menuFile->add ("Load Model...", IDC_FILE_LOADMODEL);
|
|
menuFile->add( "Refresh\tF5", IDC_FILE_REFRESH );
|
|
|
|
menuFile->addSeparator();
|
|
menuFile->add ("Save Sound Changes...", IDC_FILE_SAVESOUNDSCRIPTCHANGES );
|
|
menuFile->add( "Rebuild scenes.image...", IDC_FILE_REBUILDSCENESIMAGE );
|
|
menuFile->add( "Update scenes.image...", IDC_FILE_UPDATESCENESIMAGE );
|
|
menuFile->setEnabled( IDC_FILE_UPDATESCENESIMAGE, false );
|
|
|
|
menuFile->addSeparator();
|
|
|
|
menuFile->add ("Load Background Texture...", IDC_FILE_LOADBACKGROUNDTEX);
|
|
menuFile->add ("Load Ground Texture...", IDC_FILE_LOADGROUNDTEX);
|
|
menuFile->addSeparator ();
|
|
menuFile->add ("Unload Ground Texture", IDC_FILE_UNLOADGROUNDTEX);
|
|
menuFile->addSeparator ();
|
|
menuFile->addMenu ("Recent Files", menuRecentFiles);
|
|
menuFile->addSeparator ();
|
|
menuFile->add ("Exit", IDC_FILE_EXIT);
|
|
|
|
menuFile->setEnabled(IDC_FILE_LOADBACKGROUNDTEX, false);
|
|
menuFile->setEnabled(IDC_FILE_LOADGROUNDTEX, false);
|
|
menuFile->setEnabled(IDC_FILE_UNLOADGROUNDTEX, false);
|
|
menuFile->setEnabled(IDC_FILE_SAVESOUNDSCRIPTCHANGES, false);
|
|
|
|
menuOptions->add ("Background Color...", IDC_OPTIONS_COLORBACKGROUND);
|
|
menuOptions->add ("Ground Color...", IDC_OPTIONS_COLORGROUND);
|
|
menuOptions->add ("Light Color...", IDC_OPTIONS_COLORLIGHT);
|
|
|
|
{
|
|
menuCloseCaptionLanguages = new mxMenu();
|
|
|
|
for ( int i = 0; i < CC_NUM_LANGUAGES; i++ )
|
|
{
|
|
int id = IDC_OPTIONS_LANGUAGESTART + i;
|
|
menuCloseCaptionLanguages->add( CSentence::NameForLanguage( i ), id );
|
|
}
|
|
|
|
menuOptions->addSeparator();
|
|
menuOptions->addMenu( "CC Language", menuCloseCaptionLanguages );
|
|
}
|
|
|
|
menuOptions->addSeparator ();
|
|
menuOptions->add ("Center View", IDC_OPTIONS_CENTERVIEW);
|
|
menuOptions->add ("Center on Face", IDC_OPTIONS_CENTERONFACE );
|
|
#ifdef WIN32
|
|
menuOptions->addSeparator ();
|
|
menuOptions->add ("Make Screenshot...", IDC_OPTIONS_MAKESCREENSHOT);
|
|
//menuOptions->add ("Dump Model Info", IDC_OPTIONS_DUMP);
|
|
menuOptions->addSeparator ();
|
|
menuOptions->add ("Clear model sounds.", IDC_OPTIONS_CLEARMODELSOUNDS );
|
|
|
|
#endif
|
|
|
|
menuExpressions->add( "New...", IDC_EXPRESSIONS_NEW );
|
|
menuExpressions->addSeparator ();
|
|
menuExpressions->add( "Load...", IDC_EXPRESSIONS_LOAD );
|
|
menuExpressions->add( "Save", IDC_EXPRESSIONS_SAVE );
|
|
menuExpressions->addSeparator ();
|
|
menuExpressions->add( "Export to VFE", IDC_EXPRESSIONS_EXPORT );
|
|
menuExpressions->addSeparator ();
|
|
menuExpressions->add( "Close class", IDC_EXPRESSIONS_CLOSE );
|
|
menuExpressions->add( "Close all classes", IDC_EXPRESSIONS_CLOSEALL );
|
|
menuExpressions->addSeparator();
|
|
menuExpressions->add( "Recreate all bitmaps", IDC_EXPRESSIONS_REDOBITMAPS );
|
|
|
|
menuChoreography->add( "New...", IDC_CHOREOSCENE_NEW );
|
|
menuChoreography->addSeparator();
|
|
menuChoreography->add( "Load...", IDC_CHOREOSCENE_LOAD );
|
|
menuChoreography->add( "Save", IDC_CHOREOSCENE_SAVE );
|
|
menuChoreography->add( "Save As...", IDC_CHOREOSCENE_SAVEAS );
|
|
menuChoreography->addSeparator();
|
|
menuChoreography->add( "Close", IDC_CHOREOSCENE_CLOSE );
|
|
menuChoreography->addSeparator();
|
|
menuChoreography->add( "Add Actor...", IDC_CHOREOSCENE_ADDACTOR );
|
|
menuChoreography->addSeparator();
|
|
menuChoreography->add( "Scrubber units in seconds", IDC_CHOREOSCENE_SCRUB_UNITS );
|
|
menuChoreography->addSeparator();
|
|
menuChoreography->add( "Load Next", IDC_CHOREOSCENE_LOADNEXT );
|
|
|
|
#ifdef WIN32
|
|
menuHelp->add ("Goto Homepage...", IDC_HELP_GOTOHOMEPAGE);
|
|
menuHelp->addSeparator ();
|
|
#endif
|
|
menuHelp->add ("About...", IDC_HELP_ABOUT);
|
|
|
|
// Foundry-specific menu items
|
|
// Don't show Foundry mode in the SDK
|
|
if ( CGameConfigManager::IsSDKDeployment() == false )
|
|
{
|
|
menuFoundry->add( "Play Scene In Engine...", IDC_FOUNDRY_PLAYSCENE );
|
|
}
|
|
|
|
// create the Material System window
|
|
Con_Printf( "Creating 3D View\n" );
|
|
g_pMatSysWindow = new MatSysWindow (workspace, 0, 0, 100, 100, "", mxWindow::Normal);
|
|
|
|
Con_Printf( "Creating Close Caption tool" );
|
|
g_pCloseCaptionTool = new CloseCaptionTool( workspace );
|
|
|
|
Con_Printf( "Creating control panel\n" );
|
|
g_pControlPanel = new ControlPanel (workspace);
|
|
|
|
Con_Printf( "Creating phoneme editor\n" );
|
|
g_pPhonemeEditor = new PhonemeEditor( workspace );
|
|
|
|
Con_Printf( "Creating expression tool\n" );
|
|
g_pExpressionTool = new ExpressionTool( workspace );
|
|
|
|
Con_Printf( "Creating gesture tool\n" );
|
|
g_pGestureTool = new GestureTool( workspace );
|
|
|
|
Con_Printf( "Creating ramp tool\n" );
|
|
g_pRampTool = new RampTool( workspace );
|
|
|
|
Con_Printf( "Creating scene ramp tool\n" );
|
|
g_pSceneRampTool = new SceneRampTool( workspace );
|
|
|
|
Con_Printf( "Creating expression tray\n" );
|
|
g_pExpressionTrayTool = new mxExpressionTray( workspace, IDC_EXPRESSIONTRAY );
|
|
|
|
Con_Printf( "Creating animation browser\n" );
|
|
g_pAnimationBrowserTool = new AnimationBrowser( workspace, IDC_ANIMATIONBROWSER );
|
|
|
|
Con_Printf( "Creating flex slider window\n" );
|
|
g_pFlexPanel = new FlexPanel( workspace );
|
|
|
|
Con_Printf( "Creating wave browser\n" );
|
|
g_pWaveBrowser = new CWaveBrowser( workspace );
|
|
|
|
Con_Printf( "Creating VCD browser\n" );
|
|
g_pVCDBrowser = new CVCDBrowser( workspace );
|
|
|
|
Con_Printf( "Creating choreography view\n" );
|
|
g_pChoreoView = new CChoreoView( workspace, 200, 200, 400, 300, 0 );
|
|
// Choreo scene file drives main window title name
|
|
g_pChoreoView->SetUseForMainWindowTitle( true );
|
|
|
|
Con_Printf( "IFacePoserToolWindow::Init\n" );
|
|
|
|
IFacePoserToolWindow::InitTools();
|
|
|
|
Con_Printf( "windowtab->Init\n" );
|
|
|
|
windowtab->Init();
|
|
|
|
Con_Printf( "loadRecentFiles\n" );
|
|
|
|
loadRecentFiles ();
|
|
initRecentFiles ();
|
|
|
|
Con_Printf( "RestoreThumbnailSize\n" );
|
|
|
|
g_pExpressionTrayTool->RestoreThumbnailSize();
|
|
g_pAnimationBrowserTool->RestoreThumbnailSize();
|
|
|
|
Con_Printf( "Add Tool Windows\n" );
|
|
|
|
int c = IFacePoserToolWindow::GetToolCount();
|
|
for ( i = 0; i < c ; i++ )
|
|
{
|
|
IFacePoserToolWindow *tool = IFacePoserToolWindow::GetTool( i );
|
|
menuWindow->add( tool->GetToolName(), IDC_WINDOW_FIRSTTOOL + i );
|
|
}
|
|
|
|
menuWindow->addSeparator();
|
|
menuWindow->add( "Cascade", IDC_WINDOW_CASCADE );
|
|
menuWindow->addSeparator();
|
|
menuWindow->add( "Tile", IDC_WINDOW_TILE );
|
|
menuWindow->add( "Tile Horizontally", IDC_WINDOW_TILE_HORIZ );
|
|
menuWindow->add( "Tile Vertically", IDC_WINDOW_TILE_VERT );
|
|
menuWindow->addSeparator();
|
|
menuWindow->add( "Hide All", IDC_WINDOW_HIDEALL );
|
|
menuWindow->add( "Show All", IDC_WINDOW_SHOWALL );
|
|
|
|
Con_Printf( "UpdateWindowMenu\n" );
|
|
|
|
UpdateWindowMenu();
|
|
// Check the default item
|
|
UpdateLanguageMenu( g_viewerSettings.cclanguageid );
|
|
|
|
m_nCurrentFrame = 0;
|
|
|
|
Con_Printf( "gridsettings->Init()\n" );
|
|
|
|
gridsettings->Init();
|
|
|
|
Con_Printf( "LoadWindowPositions\n" );
|
|
|
|
LoadWindowPositions();
|
|
|
|
Con_Printf( "Model viewer created\n" );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void MDLViewer::UpdateWindowMenu( void )
|
|
{
|
|
int c = IFacePoserToolWindow::GetToolCount();
|
|
for ( int i = 0; i < c ; i++ )
|
|
{
|
|
IFacePoserToolWindow *tool = IFacePoserToolWindow::GetTool( i );
|
|
menuWindow->setChecked( IDC_WINDOW_FIRSTTOOL + i, tool->GetMxWindow()->isVisible() );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : currentLanguageId -
|
|
//-----------------------------------------------------------------------------
|
|
void MDLViewer::UpdateLanguageMenu( int currentLanguageId )
|
|
{
|
|
if ( !menuCloseCaptionLanguages )
|
|
return;
|
|
|
|
for ( int i = 0; i < CC_NUM_LANGUAGES; i++ )
|
|
{
|
|
int id = IDC_OPTIONS_LANGUAGESTART + i;
|
|
menuCloseCaptionLanguages->setChecked( id, i == currentLanguageId ? true : false );
|
|
}
|
|
}
|
|
|
|
void MDLViewer::OnDelete()
|
|
{
|
|
saveRecentFiles ();
|
|
SaveViewerRootSettings( );
|
|
|
|
#ifdef WIN32
|
|
DeleteFile ("hlmv.cfg");
|
|
DeleteFile ("midump.txt");
|
|
#endif
|
|
|
|
IFacePoserToolWindow::ShutdownTools();
|
|
|
|
g_MDLViewer = NULL;
|
|
}
|
|
|
|
MDLViewer::~MDLViewer ()
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void MDLViewer::InitModelTab( void )
|
|
{
|
|
modeltab->Init();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void MDLViewer::InitGridSettings( void )
|
|
{
|
|
gridsettings->Init();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Output : int
|
|
//-----------------------------------------------------------------------------
|
|
int MDLViewer::GetActiveModelTab( void )
|
|
{
|
|
return modeltab->getSelectedIndex();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : modelindex -
|
|
//-----------------------------------------------------------------------------
|
|
void MDLViewer::SetActiveModelTab( int modelindex )
|
|
{
|
|
modeltab->select( modelindex );
|
|
modeltab->HandleModelSelect();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Reloads the currently loaded model file.
|
|
//-----------------------------------------------------------------------------
|
|
void MDLViewer::Refresh( void )
|
|
{
|
|
Con_ColorPrintf( Color( 0, 125, 255 ), "Refreshing...\n" );
|
|
|
|
bool reinit_soundemitter = true;
|
|
|
|
// Save any changed sound script files
|
|
int c = soundemitter->GetNumSoundScripts();
|
|
for ( int i = 0; i < c; i++ )
|
|
{
|
|
if ( !soundemitter->IsSoundScriptDirty( i ) )
|
|
continue;
|
|
|
|
char const *scriptname = soundemitter->GetSoundScriptName( i );
|
|
if ( !scriptname )
|
|
continue;
|
|
|
|
if ( !filesystem->FileExists( scriptname ) ||
|
|
!filesystem->IsFileWritable( scriptname ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
int retval = mxMessageBox( NULL, va( "Save changes to sound script '%s'?", scriptname ), g_appTitle, MX_MB_YESNOCANCEL );
|
|
if ( retval != 0 )
|
|
{
|
|
reinit_soundemitter = false;
|
|
continue;
|
|
}
|
|
|
|
if ( retval == 0 )
|
|
{
|
|
soundemitter->SaveChangesToSoundScript( i );
|
|
Con_ColorPrintf( Color( 50, 255, 100 ), " saving changes to script file '%s'\n", scriptname );
|
|
}
|
|
}
|
|
|
|
// kill the soundemitter system
|
|
if ( reinit_soundemitter )
|
|
{
|
|
soundemitter->Shutdown();
|
|
}
|
|
|
|
|
|
Con_ColorPrintf( Color( 50, 255, 100 ), " reloading textures\n" );
|
|
g_pMaterialSystem->ReloadTextures();
|
|
|
|
models->ReleaseModels();
|
|
|
|
Con_ColorPrintf( Color( 50, 255, 100 ), " reloading models\n" );
|
|
models->RestoreModels();
|
|
|
|
// restart the soundemitter system
|
|
if ( reinit_soundemitter )
|
|
{
|
|
Con_ColorPrintf( Color( 50, 255, 100 ), " reloading sound emitter system\n" );
|
|
soundemitter->Init();
|
|
}
|
|
else
|
|
{
|
|
Con_ColorPrintf( Color( 250, 50, 50 ), " NOT reloading sound emitter system\n" );
|
|
}
|
|
|
|
Con_ColorPrintf( Color( 0, 125, 255 ), "done.\n" );
|
|
}
|
|
|
|
void MDLViewer::OnFileLoaded( char const *pszFile )
|
|
{
|
|
int i;
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
if (!Q_stricmp( recentFiles[i], pszFile ))
|
|
break;
|
|
}
|
|
|
|
// swap existing recent file
|
|
if (i < 8)
|
|
{
|
|
char tmp[256];
|
|
strcpy (tmp, recentFiles[0]);
|
|
strcpy (recentFiles[0], recentFiles[i]);
|
|
strcpy (recentFiles[i], tmp);
|
|
}
|
|
|
|
// insert recent file
|
|
else
|
|
{
|
|
for (i = 7; i > 0; i--)
|
|
strcpy (recentFiles[i], recentFiles[i - 1]);
|
|
|
|
strcpy( recentFiles[0], pszFile );
|
|
}
|
|
|
|
initRecentFiles ();
|
|
|
|
if ( g_pVCDBrowser )
|
|
{
|
|
g_pVCDBrowser->SetCurrent( pszFile );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Loads the file and updates the MRU list.
|
|
// Input : pszFile - File to load.
|
|
//-----------------------------------------------------------------------------
|
|
void MDLViewer::LoadModelFile( const char *pszFile )
|
|
{
|
|
models->LoadModel( pszFile );
|
|
|
|
OnFileLoaded( pszFile );
|
|
|
|
g_pControlPanel->CenterOnFace();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : *wnd -
|
|
// x -
|
|
// y -
|
|
// Output : static bool
|
|
//-----------------------------------------------------------------------------
|
|
static bool WindowContainsPoint( mxWindow *wnd, int x, int y )
|
|
{
|
|
POINT pt;
|
|
pt.x = (short)x;
|
|
pt.y = (short)y;
|
|
|
|
HWND window = (HWND)wnd->getHandle();
|
|
if ( !window )
|
|
return false;
|
|
|
|
ScreenToClient( window, &pt );
|
|
|
|
if ( pt.x < 0 )
|
|
return false;
|
|
if ( pt.y < 0 )
|
|
return false;
|
|
if ( pt.x > wnd->w() )
|
|
return false;
|
|
if ( pt.y > wnd->h() )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void MDLViewer::LoadModel_Steam()
|
|
{
|
|
if ( !g_FSDialogFactory )
|
|
return;
|
|
|
|
IFileSystemOpenDialog *pDlg;
|
|
pDlg = (IFileSystemOpenDialog*)g_FSDialogFactory( FILESYSTEMOPENDIALOG_VERSION, NULL );
|
|
if ( !pDlg )
|
|
{
|
|
char str[512];
|
|
Q_snprintf( str, sizeof( str ), "Can't create %s interface.", FILESYSTEMOPENDIALOG_VERSION );
|
|
::MessageBox( NULL, str, "Error", MB_OK );
|
|
return;
|
|
}
|
|
pDlg->Init( g_Factory, NULL );
|
|
pDlg->AddFileMask( "*.jpg" );
|
|
pDlg->AddFileMask( "*.mdl" );
|
|
pDlg->SetInitialDir( "models", "game" );
|
|
pDlg->SetFilterMdlAndJpgFiles( true );
|
|
|
|
if (pDlg->DoModal() == IDOK)
|
|
{
|
|
char filename[MAX_PATH];
|
|
pDlg->GetFilename( filename, sizeof( filename ) );
|
|
LoadModelFile( filename );
|
|
}
|
|
|
|
pDlg->Release();
|
|
}
|
|
|
|
|
|
|
|
int MDLViewer::handleEvent (mxEvent *event)
|
|
{
|
|
MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
|
|
|
|
int iret = 0;
|
|
|
|
switch (event->event)
|
|
{
|
|
case mxEvent::Size:
|
|
{
|
|
int width = w2();
|
|
int height = h2();
|
|
|
|
windowtab->SetRowHeight( WINDOW_TAB_OFFSET - 2 );
|
|
modeltab->SetRowHeight( WINDOW_TAB_OFFSET - 2 );
|
|
|
|
int gridsettingswide = 100;
|
|
int gridstart = width - gridsettingswide - 5;
|
|
|
|
int modelwide = gridstart / 3;
|
|
int windowwide = gridstart - modelwide;
|
|
|
|
int rowheight = max( windowtab->GetBestHeight( windowwide ), modeltab->GetBestHeight( modelwide ) );
|
|
|
|
workspace->setBounds( 0, 0, width, height - rowheight );
|
|
|
|
gridsettings->setBounds( gridstart, height - rowheight + 1, gridsettingswide, WINDOW_TAB_OFFSET - 2 );
|
|
|
|
windowtab->setBounds( 0, height - rowheight, windowwide, rowheight );
|
|
modeltab->setBounds( windowwide, height - rowheight, modelwide, rowheight );
|
|
|
|
iret = 1;
|
|
}
|
|
break;
|
|
case mxEvent::Action:
|
|
{
|
|
iret = 1;
|
|
switch (event->action)
|
|
{
|
|
case IDC_WINDOW_TAB:
|
|
{
|
|
windowtab->HandleWindowSelect();
|
|
}
|
|
break;
|
|
case IDC_MODEL_TAB:
|
|
{
|
|
modeltab->HandleModelSelect();
|
|
}
|
|
break;
|
|
|
|
case IDC_FILE_LOADMODEL:
|
|
{
|
|
if ( filesystem->IsSteam() )
|
|
{
|
|
g_MDLViewer->LoadModel_Steam();
|
|
}
|
|
else
|
|
{
|
|
char modelfile[ 512 ];
|
|
if ( FacePoser_ShowOpenFileNameDialog( modelfile, sizeof( modelfile ), "models", "*.mdl" ) )
|
|
{
|
|
LoadModelFile( modelfile );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_FILE_REFRESH:
|
|
{
|
|
Refresh();
|
|
break;
|
|
}
|
|
|
|
case IDC_FILE_SAVESOUNDSCRIPTCHANGES:
|
|
{
|
|
OnSaveSoundScriptChanges();
|
|
}
|
|
break;
|
|
case IDC_FILE_REBUILDSCENESIMAGE:
|
|
{
|
|
OnRebuildScenesImage();
|
|
}
|
|
break;
|
|
case IDC_FILE_UPDATESCENESIMAGE:
|
|
{
|
|
OnUpdateScenesImage();
|
|
}
|
|
break;
|
|
|
|
case IDC_FILE_LOADBACKGROUNDTEX:
|
|
case IDC_FILE_LOADGROUNDTEX:
|
|
{
|
|
const char *ptr = mxGetOpenFileName (this, 0, "*.*");
|
|
if (ptr)
|
|
{
|
|
if (0 /* g_pMatSysWindow->loadTexture (ptr, event->action - IDC_FILE_LOADBACKGROUNDTEX) */)
|
|
{
|
|
if (event->action == IDC_FILE_LOADBACKGROUNDTEX)
|
|
g_pControlPanel->setShowBackground (true);
|
|
else
|
|
g_pControlPanel->setShowGround (true);
|
|
|
|
}
|
|
else
|
|
mxMessageBox (this, "Error loading texture.", g_appTitle, MX_MB_OK | MX_MB_ERROR);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_FILE_UNLOADGROUNDTEX:
|
|
{
|
|
// g_pMatSysWindow->loadTexture (0, 1);
|
|
g_pControlPanel->setShowGround (false);
|
|
}
|
|
break;
|
|
|
|
case IDC_FILE_RECENTFILES1:
|
|
case IDC_FILE_RECENTFILES2:
|
|
case IDC_FILE_RECENTFILES3:
|
|
case IDC_FILE_RECENTFILES4:
|
|
case IDC_FILE_RECENTFILES5:
|
|
case IDC_FILE_RECENTFILES6:
|
|
case IDC_FILE_RECENTFILES7:
|
|
case IDC_FILE_RECENTFILES8:
|
|
{
|
|
int i = event->action - IDC_FILE_RECENTFILES1;
|
|
|
|
if ( recentFiles[ i ] && recentFiles[ i ][ 0 ] )
|
|
{
|
|
char ext[ 4 ];
|
|
Q_ExtractFileExtension( recentFiles[ i ], ext, sizeof( ext ) );
|
|
bool valid = false;
|
|
if ( !Q_stricmp( ext, "mdl" ) )
|
|
{
|
|
// Check extension
|
|
LoadModelFile( recentFiles[ i ] );
|
|
valid = true;
|
|
}
|
|
else if ( !Q_stricmp( ext, "vcd" ) )
|
|
{
|
|
g_pChoreoView->LoadSceneFromFile( recentFiles[ i ] );
|
|
valid = true;
|
|
}
|
|
|
|
if ( valid )
|
|
{
|
|
char tmp[256];
|
|
strcpy (tmp, recentFiles[0]);
|
|
strcpy (recentFiles[0], recentFiles[i]);
|
|
strcpy (recentFiles[i], tmp);
|
|
|
|
initRecentFiles ();
|
|
}
|
|
}
|
|
|
|
redraw ();
|
|
}
|
|
break;
|
|
|
|
case IDC_FILE_EXIT:
|
|
{
|
|
redraw ();
|
|
mx::quit ();
|
|
}
|
|
break;
|
|
|
|
case IDC_OPTIONS_COLORBACKGROUND:
|
|
case IDC_OPTIONS_COLORGROUND:
|
|
case IDC_OPTIONS_COLORLIGHT:
|
|
{
|
|
float *cols[3] = { g_viewerSettings.bgColor, g_viewerSettings.gColor, g_viewerSettings.lColor };
|
|
float *col = cols[event->action - IDC_OPTIONS_COLORBACKGROUND];
|
|
int r = (int) (col[0] * 255.0f);
|
|
int g = (int) (col[1] * 255.0f);
|
|
int b = (int) (col[2] * 255.0f);
|
|
if (mxChooseColor (this, &r, &g, &b))
|
|
{
|
|
col[0] = (float) r / 255.0f;
|
|
col[1] = (float) g / 255.0f;
|
|
col[2] = (float) b / 255.0f;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_OPTIONS_CENTERVIEW:
|
|
g_pControlPanel->centerView ();
|
|
break;
|
|
|
|
case IDC_OPTIONS_CENTERONFACE:
|
|
g_pControlPanel->CenterOnFace();
|
|
break;
|
|
|
|
case IDC_OPTIONS_CLEARMODELSOUNDS:
|
|
{
|
|
sound->StopAll();
|
|
Con_ColorPrintf( Color( 0, 100, 255 ), "Resetting model sound channels\n" );
|
|
}
|
|
break;
|
|
|
|
case IDC_OPTIONS_MAKESCREENSHOT:
|
|
{
|
|
char *ptr = (char *) mxGetSaveFileName (this, "", "*.tga");
|
|
if (ptr)
|
|
{
|
|
char fn[ 512 ];
|
|
Q_strncpy( fn, ptr, sizeof( fn ) );
|
|
Q_SetExtension( fn, ".tga", sizeof( fn ) );
|
|
g_pMatSysWindow->TakeScreenShot( fn );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_OPTIONS_DUMP:
|
|
g_pControlPanel->dumpModelInfo ();
|
|
break;
|
|
|
|
#ifdef WIN32
|
|
case IDC_HELP_GOTOHOMEPAGE:
|
|
ShellExecute (0, "open", "http://developer.valvesoftware.com/wiki/Category:Choreography", 0, 0, SW_SHOW);
|
|
break;
|
|
#endif
|
|
|
|
case IDC_HELP_ABOUT:
|
|
mxMessageBox (this,
|
|
"v1.0 Copyright © 1996-2007, Valve Corporation. All rights reserved.\r\nBuild Date: " __DATE__ "",
|
|
"Valve Face Poser",
|
|
MX_MB_OK | MX_MB_INFORMATION);
|
|
break;
|
|
|
|
case IDC_EXPRESSIONS_REDOBITMAPS:
|
|
{
|
|
CExpClass *active = expressions->GetActiveClass();
|
|
if ( active )
|
|
{
|
|
g_pProgressDialog->Start( "Rebuild Bitmaps", "", true );
|
|
|
|
g_pMatSysWindow->EnableStickySnapshotMode( );
|
|
for ( int i = 0; i < active->GetNumExpressions() ; i++ )
|
|
{
|
|
CExpression *exp = active->GetExpression( i );
|
|
if ( !exp )
|
|
continue;
|
|
|
|
g_pProgressDialog->UpdateText( exp->name );
|
|
g_pProgressDialog->Update( (float)i / (float)active->GetNumExpressions() );
|
|
if ( g_pProgressDialog->IsCancelled() )
|
|
{
|
|
Msg( "Cancelled\n" );
|
|
break;
|
|
}
|
|
|
|
exp->CreateNewBitmap( models->GetActiveModelIndex() );
|
|
|
|
if ( ! ( i % 5 ) )
|
|
{
|
|
g_pExpressionTrayTool->redraw();
|
|
}
|
|
}
|
|
g_pMatSysWindow->DisableStickySnapshotMode( );
|
|
|
|
g_pProgressDialog->Finish();
|
|
|
|
active->SelectExpression( 0 );
|
|
}
|
|
}
|
|
break;
|
|
case IDC_EXPRESSIONS_NEW:
|
|
{
|
|
char classfile[ 512 ];
|
|
if ( FacePoser_ShowSaveFileNameDialog( classfile, sizeof( classfile ), "expressions", "*.txt" ) )
|
|
{
|
|
Q_DefaultExtension( classfile, ".txt", sizeof( classfile ) );
|
|
expressions->CreateNewClass( classfile );
|
|
}
|
|
}
|
|
break;
|
|
case IDC_EXPRESSIONS_LOAD:
|
|
{
|
|
char classfile[ 512 ];
|
|
if ( FacePoser_ShowOpenFileNameDialog( classfile, sizeof( classfile ), "expressions", "*.txt" ) )
|
|
{
|
|
expressions->LoadClass( classfile );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_EXPRESSIONS_SAVE:
|
|
{
|
|
CExpClass *active = expressions->GetActiveClass();
|
|
if ( active )
|
|
{
|
|
active->Save();
|
|
active->Export();
|
|
}
|
|
}
|
|
break;
|
|
case IDC_EXPRESSIONS_EXPORT:
|
|
{
|
|
CExpClass *active = expressions->GetActiveClass();
|
|
if ( active )
|
|
{
|
|
active->Export();
|
|
}
|
|
}
|
|
break;
|
|
case IDC_EXPRESSIONS_CLOSE:
|
|
g_pControlPanel->Close();
|
|
break;
|
|
case IDC_EXPRESSIONS_CLOSEALL:
|
|
g_pControlPanel->Closeall();
|
|
break;
|
|
case IDC_CHOREOSCENE_NEW:
|
|
g_pChoreoView->New();
|
|
break;
|
|
case IDC_CHOREOSCENE_LOAD:
|
|
g_pChoreoView->Load();
|
|
break;
|
|
case IDC_CHOREOSCENE_LOADNEXT:
|
|
g_pChoreoView->LoadNext();
|
|
break;
|
|
case IDC_CHOREOSCENE_SAVE:
|
|
g_pChoreoView->Save();
|
|
break;
|
|
case IDC_CHOREOSCENE_SAVEAS:
|
|
g_pChoreoView->SaveAs();
|
|
break;
|
|
case IDC_CHOREOSCENE_CLOSE:
|
|
g_pChoreoView->Close();
|
|
break;
|
|
case IDC_CHOREOSCENE_ADDACTOR:
|
|
g_pChoreoView->NewActor();
|
|
break;
|
|
case IDC_CHOREOSCENE_SCRUB_UNITS:
|
|
{
|
|
g_pChoreoView->SetScrubUnitSeconds( !menuChoreography->isChecked( IDC_CHOREOSCENE_SCRUB_UNITS ));
|
|
menuChoreography->setChecked( IDC_CHOREOSCENE_SCRUB_UNITS, !menuChoreography->isChecked( IDC_CHOREOSCENE_SCRUB_UNITS ) );
|
|
}
|
|
break;
|
|
case IDC_WINDOW_TILE:
|
|
{
|
|
OnTile();
|
|
}
|
|
break;
|
|
case IDC_WINDOW_TILE_HORIZ:
|
|
{
|
|
OnTileHorizontally();
|
|
}
|
|
break;
|
|
case IDC_WINDOW_TILE_VERT:
|
|
{
|
|
OnTileVertically();
|
|
}
|
|
break;
|
|
case IDC_WINDOW_CASCADE:
|
|
{
|
|
OnCascade();
|
|
}
|
|
break;
|
|
case IDC_WINDOW_HIDEALL:
|
|
{
|
|
OnHideAll();
|
|
}
|
|
break;
|
|
case IDC_WINDOW_SHOWALL:
|
|
{
|
|
OnShowAll();
|
|
}
|
|
break;
|
|
case IDC_FOUNDRY_PLAYSCENE:
|
|
{
|
|
OnPlaySceneInFoundry();
|
|
}
|
|
default:
|
|
{
|
|
iret = 0;
|
|
int tool_number = event->action - IDC_WINDOW_FIRSTTOOL;
|
|
int max_tools = IDC_WINDOW_LASTTOOL - IDC_WINDOW_FIRSTTOOL;
|
|
|
|
if ( tool_number >= 0 &&
|
|
tool_number <= max_tools &&
|
|
tool_number < IFacePoserToolWindow::GetToolCount() )
|
|
{
|
|
iret = 1;
|
|
IFacePoserToolWindow *tool = IFacePoserToolWindow::GetTool( tool_number );
|
|
if ( tool )
|
|
{
|
|
mxWindow *toolw = tool->GetMxWindow();
|
|
|
|
bool wasvisible = toolw->isVisible();
|
|
toolw->setVisible( !wasvisible );
|
|
|
|
g_MDLViewer->UpdateWindowMenu();
|
|
|
|
}
|
|
}
|
|
|
|
int lang_number = event->action - IDC_OPTIONS_LANGUAGESTART;
|
|
if ( lang_number >= 0 &&
|
|
lang_number < CC_NUM_LANGUAGES )
|
|
{
|
|
iret = 1;
|
|
SetCloseCaptionLanguageId( lang_number );
|
|
}
|
|
}
|
|
break;
|
|
} //switch (event->action)
|
|
} // mxEvent::Action
|
|
break;
|
|
case KeyDown:
|
|
{
|
|
//g_pMatSysWindow->handleEvent(event);
|
|
// Send it to the active tool
|
|
IFacePoserToolWindow *active = IFacePoserToolWindow::GetActiveTool();
|
|
if ( active )
|
|
{
|
|
mxWindow *w = active->GetMxWindow();
|
|
if ( w )
|
|
{
|
|
w->handleEvent( event );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_pMatSysWindow->handleEvent(event);
|
|
}
|
|
iret = 1;
|
|
}
|
|
break;
|
|
case mxEvent::Activate:
|
|
{
|
|
if (event->action)
|
|
{
|
|
mx::setIdleWindow( g_pMatSysWindow );
|
|
// Force reload of localization data
|
|
SetCloseCaptionLanguageId( GetCloseCaptionLanguageId(), true );
|
|
}
|
|
else
|
|
{
|
|
mx::setIdleWindow( 0 );
|
|
}
|
|
iret = 1;
|
|
}
|
|
break;
|
|
} // event->event
|
|
|
|
return iret;
|
|
}
|
|
|
|
void MDLViewer::SaveWindowPositions( void )
|
|
{
|
|
// Save the model viewer position
|
|
SavePosition();
|
|
|
|
int c = IFacePoserToolWindow::GetToolCount();
|
|
for ( int i = 0; i < c; i++ )
|
|
{
|
|
IFacePoserToolWindow *w = IFacePoserToolWindow::GetTool( i );
|
|
w->SavePosition();
|
|
}
|
|
}
|
|
|
|
void MDLViewer::LoadWindowPositions( void )
|
|
{
|
|
// NOTE: Don't do this here, we do the mdlviewer position earlier in startup
|
|
// LoadPosition();
|
|
|
|
int w = this->w();
|
|
int h = this->h();
|
|
|
|
g_viewerSettings.width = w;
|
|
g_viewerSettings.height = h;
|
|
|
|
int c = IFacePoserToolWindow::GetToolCount();
|
|
for ( int i = 0; i < c; i++ )
|
|
{
|
|
IFacePoserToolWindow *w = IFacePoserToolWindow::GetTool( i );
|
|
w->LoadPosition();
|
|
}
|
|
}
|
|
|
|
void
|
|
MDLViewer::redraw ()
|
|
{
|
|
}
|
|
|
|
int MDLViewer::GetCurrentFrame( void )
|
|
{
|
|
return m_nCurrentFrame;
|
|
}
|
|
|
|
void MDLViewer::Think( float dt )
|
|
{
|
|
++m_nCurrentFrame;
|
|
|
|
// Iterate across tools
|
|
IFacePoserToolWindow::ToolThink( dt );
|
|
|
|
sound->Update( dt );
|
|
|
|
bool soundscriptsdirty = AreSoundScriptsDirty();
|
|
if ( soundscriptsdirty != m_bOldSoundScriptsDirty )
|
|
{
|
|
// Update the menu item when this changes
|
|
menuFile->setEnabled(IDC_FILE_SAVESOUNDSCRIPTCHANGES, soundscriptsdirty );
|
|
}
|
|
|
|
m_bOldSoundScriptsDirty = soundscriptsdirty;
|
|
}
|
|
|
|
static int CountVisibleTools( void )
|
|
{
|
|
int i;
|
|
int c = IFacePoserToolWindow::GetToolCount();
|
|
int viscount = 0;
|
|
|
|
for ( i = 0; i < c; i++ )
|
|
{
|
|
IFacePoserToolWindow *tool = IFacePoserToolWindow::GetTool( i );
|
|
mxWindow *w = tool->GetMxWindow();
|
|
if ( !w->isVisible() )
|
|
continue;
|
|
|
|
viscount++;
|
|
}
|
|
|
|
return viscount;
|
|
}
|
|
|
|
void MDLViewer::OnCascade()
|
|
{
|
|
int i;
|
|
int c = IFacePoserToolWindow::GetToolCount();
|
|
int viscount = CountVisibleTools();
|
|
|
|
int x = 0, y = 0;
|
|
|
|
int offset = 20;
|
|
|
|
int wide = workspace->w2() - viscount * offset;
|
|
int tall = ( workspace->h2() - viscount * offset ) / 2;
|
|
|
|
for ( i = 0; i < c; i++ )
|
|
{
|
|
IFacePoserToolWindow *tool = IFacePoserToolWindow::GetTool( i );
|
|
mxWindow *w = tool->GetMxWindow();
|
|
if ( !w->isVisible() )
|
|
continue;
|
|
|
|
w->setBounds( x, y, wide, tall );
|
|
x += offset;
|
|
y += offset;
|
|
}
|
|
}
|
|
|
|
void MDLViewer::OnTile()
|
|
{
|
|
int c = CountVisibleTools();
|
|
|
|
int rows = (int)sqrt( ( float )c );
|
|
rows = clamp( rows, 1, rows );
|
|
|
|
int cols = 1;
|
|
while ( rows * cols < c )
|
|
{
|
|
cols++;
|
|
}
|
|
|
|
DoTile( rows, cols );
|
|
}
|
|
|
|
void MDLViewer::OnTileHorizontally()
|
|
{
|
|
int c = CountVisibleTools();
|
|
|
|
DoTile( c, 1 );
|
|
}
|
|
|
|
void MDLViewer::OnTileVertically()
|
|
{
|
|
int c = CountVisibleTools();
|
|
|
|
DoTile( 1, c );
|
|
}
|
|
|
|
void MDLViewer::OnHideAll()
|
|
{
|
|
int c = IFacePoserToolWindow::GetToolCount();
|
|
for ( int i = 0; i < c; i++ )
|
|
{
|
|
IFacePoserToolWindow *tool = IFacePoserToolWindow::GetTool( i );
|
|
mxWindow *w = tool->GetMxWindow();
|
|
|
|
w->setVisible( false );
|
|
}
|
|
|
|
UpdateWindowMenu();
|
|
}
|
|
|
|
void MDLViewer::OnShowAll()
|
|
{
|
|
int c = IFacePoserToolWindow::GetToolCount();
|
|
for ( int i = 0; i < c; i++ )
|
|
{
|
|
IFacePoserToolWindow *tool = IFacePoserToolWindow::GetTool( i );
|
|
mxWindow *w = tool->GetMxWindow();
|
|
|
|
w->setVisible( true );
|
|
}
|
|
|
|
UpdateWindowMenu();
|
|
}
|
|
|
|
void MDLViewer::DoTile( int x, int y )
|
|
{
|
|
int c = IFacePoserToolWindow::GetToolCount();
|
|
|
|
if ( x < 1 )
|
|
x = 1;
|
|
if ( y < 1 )
|
|
y = 1;
|
|
|
|
int wide = workspace->w2() / y;
|
|
int tall = workspace->h2() / x;
|
|
|
|
int obj = 0;
|
|
|
|
for ( int row = 0 ; row < x ; row++ )
|
|
{
|
|
for ( int col = 0; col < y; col++ )
|
|
{
|
|
bool found = false;
|
|
while ( 1 )
|
|
{
|
|
if ( obj >= c )
|
|
break;
|
|
|
|
IFacePoserToolWindow *tool = IFacePoserToolWindow::GetTool( obj++ );
|
|
mxWindow *w = tool->GetMxWindow();
|
|
if ( w->isVisible() )
|
|
{
|
|
w->setBounds( col * wide, row * tall, wide, tall );
|
|
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !found )
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Not used by faceposer
|
|
// Output : int
|
|
//-----------------------------------------------------------------------------
|
|
int MDLViewer::GetCurrentHitboxSet(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Output : Returns true on success, false on failure.
|
|
//-----------------------------------------------------------------------------
|
|
bool MDLViewer::PaintBackground( void )
|
|
{
|
|
CChoreoWidgetDrawHelper drawHelper( this );
|
|
|
|
RECT rc;
|
|
drawHelper.GetClientRect( rc );
|
|
|
|
drawHelper.DrawFilledRect( COLOR_CHOREO_BACKGROUND, rc );
|
|
return false;
|
|
}
|
|
|
|
void MDLViewer::OnUpdateScenesImage()
|
|
{
|
|
if ( m_vecDirtyVCDs.Count() > 0 )
|
|
{
|
|
g_pProgressDialog->Start( "Updating scenes.image", "", false );
|
|
|
|
CUtlBuffer targetBuffer;
|
|
|
|
bool bLittleEndian = true;
|
|
|
|
const char *pFilename = bLittleEndian ? "scenes/scenes.image" : "scenes/scenes.360.image";
|
|
char szFilename[MAX_PATH];
|
|
Q_strncpy( szFilename, gamedir, sizeof(szFilename) );
|
|
Q_strncat( szFilename, pFilename, sizeof(szFilename) );
|
|
|
|
CP4AutoEditAddFile checkout( szFilename );
|
|
|
|
bool bSuccess = false;
|
|
|
|
// Load existing file
|
|
if ( scriptlib->ReadFileToBuffer( szFilename, targetBuffer ) )
|
|
{
|
|
bSuccess = g_pSceneImage->UpdateSceneImageFile( targetBuffer, gamedir, bLittleEndian, false, this, m_vecDirtyVCDs.Base(), m_vecDirtyVCDs.Count() );
|
|
}
|
|
// Error loading, or didn't exist, do the full image creation
|
|
else
|
|
{
|
|
bSuccess = g_pSceneImage->CreateSceneImageFile( targetBuffer, gamedir, bLittleEndian, false, this );
|
|
}
|
|
|
|
if ( bSuccess )
|
|
{
|
|
MakeFileWriteable( szFilename );
|
|
scriptlib->WriteBufferToFile( szFilename, targetBuffer, WRITE_TO_DISK_ALWAYS );
|
|
}
|
|
|
|
g_pProgressDialog->Finish();
|
|
m_vecDirtyVCDs.RemoveAll();
|
|
}
|
|
|
|
UpdateTheUpdateScenesImageMenu();
|
|
}
|
|
|
|
void MDLViewer::OnRebuildScenesImage()
|
|
{
|
|
g_pProgressDialog->Start( "Rebuilding scenes.image", "", false );
|
|
|
|
CUtlBuffer targetBuffer;
|
|
|
|
bool bLittleEndian = true;
|
|
|
|
const char *pFilename = bLittleEndian ? "scenes/scenes.image" : "scenes/scenes.360.image";
|
|
char szModDir[MAX_PATH];
|
|
Q_strncpy( szModDir, gamedir, sizeof(szModDir) );
|
|
V_StripTrailingSlash( szModDir );
|
|
|
|
char szDLCPath[MAX_PATH];
|
|
|
|
int nHighestDLC = 1;
|
|
for ( ;nHighestDLC <= 99; nHighestDLC++ )
|
|
{
|
|
V_snprintf( szDLCPath, sizeof( szDLCPath ), "%s_dlc%d", szModDir, nHighestDLC );
|
|
if ( !filesystem->IsDirectory( szDLCPath ) )
|
|
{
|
|
// does not exist, highest dlc available is previous
|
|
nHighestDLC--;
|
|
break;
|
|
}
|
|
|
|
V_snprintf( szDLCPath, sizeof( szDLCPath ), "%s_dlc%d/dlc_disabled.txt", szModDir, nHighestDLC );
|
|
if ( filesystem->FileExists( szDLCPath ) )
|
|
{
|
|
// disabled, highest dlc available is previous
|
|
nHighestDLC--;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( nHighestDLC > 0 )
|
|
{
|
|
V_snprintf( szDLCPath, sizeof( szDLCPath ), "%s_dlc%d/%s", szModDir, nHighestDLC, pFilename );
|
|
}
|
|
else
|
|
{
|
|
V_snprintf( szDLCPath, sizeof( szDLCPath ), "%s/%s", szModDir, pFilename );
|
|
}
|
|
|
|
CP4AutoEditAddFile checkout( szDLCPath );
|
|
|
|
bool bSuccess = g_pSceneImage->CreateSceneImageFile( targetBuffer, gamedir, bLittleEndian, false, this );
|
|
if ( bSuccess )
|
|
{
|
|
MakeFileWriteable( szDLCPath );
|
|
scriptlib->WriteBufferToFile( szDLCPath, targetBuffer, WRITE_TO_DISK_ALWAYS );
|
|
}
|
|
|
|
g_pProgressDialog->Finish();
|
|
m_vecDirtyVCDs.RemoveAll();
|
|
|
|
UpdateTheUpdateScenesImageMenu();
|
|
}
|
|
|
|
|
|
|
|
bool SendConsoleCommandToEngine( const char* szConsoleCommand, const char* szCopyDataFailedMsg, const char* szEngineNotRunningMsg = "The Source engine must be running in order to utilize this feature." )
|
|
{
|
|
bool bRetVal = false;
|
|
const HWND hwndEngine = FindWindow( "Valve001", NULL );
|
|
|
|
// Can't find the engine
|
|
if ( hwndEngine == NULL )
|
|
{
|
|
::MessageBox( NULL, szEngineNotRunningMsg, "Source Engine Not Running", MB_OK | MB_ICONEXCLAMATION );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Fill out the data structure to send to the engine.
|
|
//
|
|
COPYDATASTRUCT copyData;
|
|
copyData.cbData = strlen( szConsoleCommand ) + 1;
|
|
copyData.dwData = 0;
|
|
copyData.lpData = ( void * )szConsoleCommand;
|
|
|
|
if ( !SendMessageA( hwndEngine, WM_COPYDATA, 0, (LPARAM)©Data ) )
|
|
{
|
|
::MessageBox( NULL, szCopyDataFailedMsg, "Source Engine Declined Request", MB_OK | MB_ICONEXCLAMATION );
|
|
}
|
|
else
|
|
{
|
|
bRetVal = true;
|
|
::SetFocus( hwndEngine );
|
|
|
|
}
|
|
}
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
void MDLViewer::OnPlaySceneInFoundry()
|
|
{
|
|
const CChoreoScene *scene = g_pChoreoView->GetScene();
|
|
|
|
if ( NULL != scene )
|
|
{
|
|
// Rebuild the scenes.image file
|
|
OnRebuildScenesImage();
|
|
|
|
// Instruct the engine to flush the scene cache and reload the scenes.image file
|
|
SendConsoleCommandToEngine( "scene_flush\n", "Unable to clear scene_cache." );
|
|
|
|
// Instruct the engine to load the savegame that was created right before the given scene was to be played
|
|
char szConsoleCommand[MAX_PATH];
|
|
char szSceneFileName[MAX_PATH];
|
|
|
|
V_FileBase( scene->GetFilename(), szSceneFileName, sizeof( szSceneFileName ) );
|
|
V_snprintf( szConsoleCommand, sizeof( szConsoleCommand ), "load faceposer\\%s\n", szSceneFileName );
|
|
SendConsoleCommandToEngine( szConsoleCommand, "Unable to load savegame for requested scene." );
|
|
}
|
|
else
|
|
{
|
|
::MessageBox( NULL, "There is no scene presently loaded. Please load a scene using Choreography|Load... before attempting to play the scene inside the engine.", "No Scene Loaded", MB_OK | MB_ICONEXCLAMATION );
|
|
}
|
|
}
|
|
|
|
|
|
void MDLViewer::UpdateStatus( char const *pchSceneName, bool bQuiet, int nIndex, int nCount )
|
|
{
|
|
g_pProgressDialog->UpdateText( pchSceneName );
|
|
g_pProgressDialog->Update( (float)nIndex / (float)nCount );
|
|
}
|
|
|
|
void MDLViewer::OnVCDSaved( char const *pFullpath )
|
|
{
|
|
CUtlString str;
|
|
str = pFullpath;
|
|
m_vecDirtyVCDs.AddToTail( str );
|
|
|
|
UpdateTheUpdateScenesImageMenu();
|
|
if ( m_bAlwaysUpdate )
|
|
{
|
|
OnUpdateScenesImage();
|
|
}
|
|
}
|
|
|
|
void MDLViewer::UpdateTheUpdateScenesImageMenu()
|
|
{
|
|
mb->setEnabled( IDC_FILE_UPDATESCENESIMAGE, m_vecDirtyVCDs.Count() > 0 );
|
|
}
|
|
|
|
void MDLViewer::OnSaveSoundScriptChanges()
|
|
{
|
|
if ( !AreSoundScriptsDirty() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Save any changed sound script files
|
|
int c = soundemitter->GetNumSoundScripts();
|
|
for ( int i = 0; i < c; i++ )
|
|
{
|
|
if ( !soundemitter->IsSoundScriptDirty( i ) )
|
|
continue;
|
|
|
|
char const *scriptname = soundemitter->GetSoundScriptName( i );
|
|
if ( !scriptname )
|
|
continue;
|
|
|
|
if ( !filesystem->FileExists( scriptname ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( !filesystem->IsFileWritable( scriptname ) )
|
|
{
|
|
mxMessageBox( NULL, va( "Can't save changes to sound script '%s', file is READ-ONLY?", scriptname ), g_appTitle, MX_MB_OK );
|
|
continue;
|
|
}
|
|
|
|
int retval = mxMessageBox( NULL, va( "Save changes to sound script '%s'?", scriptname ), g_appTitle, MX_MB_YESNOCANCEL );
|
|
if ( retval == 2 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( retval == 0 )
|
|
{
|
|
soundemitter->SaveChangesToSoundScript( i );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// The application object
|
|
//-----------------------------------------------------------------------------
|
|
class CHLFacePoserApp : public CTier3SteamApp
|
|
{
|
|
typedef CTier3SteamApp BaseClass;
|
|
|
|
public:
|
|
// Methods of IApplication
|
|
virtual bool Create();
|
|
virtual bool PreInit();
|
|
virtual int Main();
|
|
virtual void PostShutdown();
|
|
virtual void Destroy();
|
|
|
|
private:
|
|
// Sets up the search paths
|
|
bool SetupSearchPaths();
|
|
};
|
|
|
|
|
|
class CHLFacePoserLoggingListener : public ILoggingListener
|
|
{
|
|
public:
|
|
virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
|
|
{
|
|
g_bInError = true;
|
|
|
|
switch ( pContext->m_Severity )
|
|
{
|
|
case LS_ERROR:
|
|
Plat_MessageBox( "Error", pMessage );
|
|
g_bInError = false;
|
|
break;
|
|
case LS_WARNING:
|
|
Con_ErrorPrintf( pMessage );
|
|
g_bInError = false;
|
|
break;
|
|
|
|
case LS_MESSAGE:
|
|
Con_Printf( pMessage );
|
|
g_bInError = false;
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
static CHLFacePoserLoggingListener s_HLFacePoserLoggingListener;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Create all singleton systems
|
|
//-----------------------------------------------------------------------------
|
|
bool CHLFacePoserApp::Create()
|
|
{
|
|
// Save some memory so engine/hammer isn't so painful
|
|
CommandLine()->AppendParm( "-disallowhwmorph", NULL );
|
|
|
|
LoggingSystem_PushLoggingState();
|
|
LoggingSystem_RegisterLoggingListener( &s_HLFacePoserLoggingListener );
|
|
|
|
AppSystemInfo_t appSystems[] =
|
|
{
|
|
{ "inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION },
|
|
{ "materialsystem.dll", MATERIAL_SYSTEM_INTERFACE_VERSION },
|
|
{ "studiorender.dll", STUDIO_RENDER_INTERFACE_VERSION },
|
|
{ "vphysics.dll", VPHYSICS_INTERFACE_VERSION },
|
|
{ "datacache.dll", DATACACHE_INTERFACE_VERSION },
|
|
{ "datacache.dll", MDLCACHE_INTERFACE_VERSION },
|
|
{ "datacache.dll", STUDIO_DATA_CACHE_INTERFACE_VERSION },
|
|
{ "vgui2.dll", VGUI_IVGUI_INTERFACE_VERSION },
|
|
{ "soundemittersystem.dll", SOUNDEMITTERSYSTEM_INTERFACE_VERSION },
|
|
{ "", "" } // Required to terminate the list
|
|
};
|
|
|
|
if ( !AddSystems( appSystems ) )
|
|
return false;
|
|
|
|
// Add the P4 module separately so that if it is absent (say in the SDK) then the other system will initialize properly
|
|
if ( CGameConfigManager::IsSDKDeployment() == false )
|
|
{
|
|
AppModule_t p4Module = LoadModule( "p4lib.dll" );
|
|
AddSystem( p4Module, P4_INTERFACE_VERSION );
|
|
}
|
|
|
|
g_Factory = GetFactory();
|
|
|
|
IMaterialSystem* pMaterialSystem = (IMaterialSystem*)FindSystem( MATERIAL_SYSTEM_INTERFACE_VERSION );
|
|
if ( !pMaterialSystem )
|
|
{
|
|
Warning( "Material System interface could not be found!\n" );
|
|
return false;
|
|
}
|
|
|
|
const char *pShaderDLL = CommandLine()->ParmValue("-shaderdll");
|
|
if(!pShaderDLL)
|
|
{
|
|
pShaderDLL = "shaderapidx9.dll";
|
|
}
|
|
pMaterialSystem->SetShaderAPI( pShaderDLL );
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void CHLFacePoserApp::Destroy()
|
|
{
|
|
LoggingSystem_PopLoggingState();
|
|
}
|
|
|
|
|
|
const char *GetGameDirectory()
|
|
{
|
|
// TODO: get rid of this and ONLY use the filesystem, so hlfaceposer works nicely for
|
|
// mods that get the base game resources from the Steam filesystem.
|
|
return gamedir;
|
|
}
|
|
|
|
char const *GetGameDirectorySimple()
|
|
{
|
|
return gamedirsimple;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sets up the game path
|
|
//-----------------------------------------------------------------------------
|
|
bool CHLFacePoserApp::SetupSearchPaths()
|
|
{
|
|
// Add paths...
|
|
if ( !BaseClass::SetupSearchPaths( NULL, false, true ) )
|
|
return false;
|
|
|
|
// Set gamedir.
|
|
Q_MakeAbsolutePath( gamedir, sizeof( gamedir ), GetGameInfoPath() );
|
|
|
|
Q_FileBase( gamedir, gamedirsimple, sizeof( gamedirsimple ) );
|
|
|
|
Q_AppendSlash( gamedir, sizeof( gamedir ) );
|
|
|
|
workspacefiles->Init( GetGameDirectorySimple() );
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Init, shutdown
|
|
//-----------------------------------------------------------------------------
|
|
bool CHLFacePoserApp::PreInit( )
|
|
{
|
|
if ( !BaseClass::PreInit() )
|
|
return false;
|
|
|
|
g_pFileSystem = filesystem = g_pFullFileSystem;
|
|
g_pStudioDataCache = (IStudioDataCache*)FindSystem( STUDIO_DATA_CACHE_INTERFACE_VERSION );
|
|
physcollision = (IPhysicsCollision *)FindSystem( VPHYSICS_COLLISION_INTERFACE_VERSION );
|
|
physprop = (IPhysicsSurfaceProps *)FindSystem( VPHYSICS_SURFACEPROPS_INTERFACE_VERSION );
|
|
soundemitter = (ISoundEmitterSystemBase*)FindSystem(SOUNDEMITTERSYSTEM_INTERFACE_VERSION);
|
|
|
|
if ( !soundemitter || !g_pLocalize || !filesystem || !physprop || !physcollision ||
|
|
!g_pMaterialSystem || !g_pStudioRender || !g_pMDLCache || !g_pDataCache )
|
|
{
|
|
Error("Unable to load required library interface!\n");
|
|
}
|
|
|
|
MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, false, false, false, false );
|
|
filesystem->SetWarningFunc( Warning );
|
|
|
|
// Add paths...
|
|
if ( !SetupSearchPaths() )
|
|
return false;
|
|
|
|
// Get the adapter from the command line....
|
|
const char *pAdapterString;
|
|
int nAdapter = 0;
|
|
if (CommandLine()->CheckParm( "-adapter", &pAdapterString ))
|
|
{
|
|
nAdapter = atoi( pAdapterString );
|
|
}
|
|
|
|
int adapterFlags = MATERIAL_INIT_ALLOCATE_FULLSCREEN_TEXTURE;
|
|
if ( CommandLine()->CheckParm( "-ref" ) )
|
|
{
|
|
adapterFlags |= MATERIAL_INIT_REFERENCE_RASTERIZER;
|
|
}
|
|
|
|
g_pMaterialSystem->SetAdapter( nAdapter, adapterFlags );
|
|
|
|
LoadFileSystemDialogModule();
|
|
|
|
return true;
|
|
}
|
|
|
|
void CHLFacePoserApp::PostShutdown()
|
|
{
|
|
UnloadFileSystemDialogModule();
|
|
|
|
g_pFileSystem = filesystem = NULL;
|
|
g_pStudioDataCache = NULL;
|
|
physcollision = NULL;
|
|
physprop = NULL;
|
|
|
|
BaseClass::PostShutdown();
|
|
|
|
g_Factory = NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// main application
|
|
//-----------------------------------------------------------------------------
|
|
int CHLFacePoserApp::Main()
|
|
{
|
|
// Do Perforce Stuff
|
|
g_p4factory->SetDummyMode( false );
|
|
if ( CommandLine()->FindParm( "-nop4" ) || CGameConfigManager::IsSDKDeployment() )
|
|
{
|
|
g_p4factory->SetDummyMode( true );
|
|
}
|
|
|
|
g_p4factory->SetOpenFileChangeList( "FacePoser Auto Checkout" );
|
|
|
|
g_pMaterialSystem->ModInit();
|
|
|
|
g_pDataCache->SetSize( 64 * 1024 * 1024 );
|
|
|
|
// Always start with english
|
|
g_pLocalize->AddFile( "resource/closecaption_english.txt", "GAME", true );
|
|
|
|
sound->Init();
|
|
|
|
IFacePoserToolWindow::EnableToolRedraw( false );
|
|
|
|
g_MDLViewer = new MDLViewer ();
|
|
g_MDLViewer->setMenuBar (g_MDLViewer->getMenuBar ());
|
|
|
|
// Force reload of close captioning data file!!!
|
|
SetCloseCaptionLanguageId( g_viewerSettings.cclanguageid, true );
|
|
|
|
g_pStudioModel->Init();
|
|
|
|
int i;
|
|
bool modelloaded = false;
|
|
for ( i = 1; i < CommandLine()->ParmCount(); i++ )
|
|
{
|
|
if ( Q_stristr (CommandLine()->GetParm( i ), ".mdl") )
|
|
{
|
|
modelloaded = true;
|
|
g_MDLViewer->LoadModelFile( CommandLine()->GetParm( i ) );
|
|
break;
|
|
}
|
|
}
|
|
|
|
models->LoadModelList();
|
|
g_pPhonemeEditor->ValidateSpeechAPIIndex();
|
|
|
|
if ( models->Count() == 0 )
|
|
{
|
|
g_pFlexPanel->initFlexes( );
|
|
}
|
|
|
|
// Load expressions from last time
|
|
int files = workspacefiles->GetNumStoredFiles( IWorkspaceFiles::EXPRESSION );
|
|
for ( i = 0; i < files; i++ )
|
|
{
|
|
expressions->LoadClass( workspacefiles->GetStoredFile( IWorkspaceFiles::EXPRESSION, i ) );
|
|
}
|
|
|
|
IFacePoserToolWindow::EnableToolRedraw( true );
|
|
|
|
int nRetVal = mx::run ();
|
|
|
|
if (g_pStudioModel)
|
|
{
|
|
g_pStudioModel->Shutdown();
|
|
g_pStudioModel = NULL;
|
|
}
|
|
|
|
g_pMaterialSystem->ModShutdown();
|
|
return nRetVal;
|
|
}
|
|
|
|
static bool CHLFacePoserApp_SuggestGameInfoDirFn( CFSSteamSetupInfo const *pFsSteamSetupInfo, char *pchPathBuffer, int nBufferLength, bool *pbBubbleDirectories )
|
|
{
|
|
if ( pbBubbleDirectories )
|
|
*pbBubbleDirectories = true;
|
|
|
|
for ( int i = 1; i < CommandLine()->ParmCount(); i++ )
|
|
{
|
|
if ( Q_stristr( CommandLine()->GetParm( i ), ".mdl" ) )
|
|
{
|
|
Q_MakeAbsolutePath( pchPathBuffer, nBufferLength, CommandLine()->GetParm( i ) );
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int main (int argc, char *argv[])
|
|
{
|
|
CommandLine()->CreateCmdLine( argc, argv );
|
|
CoInitialize(NULL);
|
|
|
|
// make sure, we start in the right directory
|
|
char szName[256];
|
|
strcpy (szName, mx::getApplicationPath() );
|
|
mx::init (argc, argv);
|
|
|
|
char workingdir[ 256 ];
|
|
workingdir[0] = 0;
|
|
Q_getwd( workingdir, sizeof( workingdir ) );
|
|
|
|
// Set game info directory suggestion callback
|
|
SetSuggestGameInfoDirFn( CHLFacePoserApp_SuggestGameInfoDirFn );
|
|
|
|
CHLFacePoserApp hlFacePoserApp;
|
|
CSteamApplication steamApplication( &hlFacePoserApp );
|
|
int nRetVal = steamApplication.Run();
|
|
|
|
CoUninitialize();
|
|
|
|
return nRetVal;
|
|
}
|
|
|