702 lines
18 KiB
C++
702 lines
18 KiB
C++
|
//
|
|||
|
// Half-Life Model Viewer (c) 1999 by Mete Ciragan
|
|||
|
//
|
|||
|
// file: mdlviewer.cpp
|
|||
|
// last modified: Jun 03 1999, Mete Ciragan
|
|||
|
// copyright: The programs and associated files contained in this
|
|||
|
// distribution were developed by Mete Ciragan. The programs
|
|||
|
// are not in the public domain, but they are freely
|
|||
|
// distributable without licensing fees. These programs are
|
|||
|
// provided without guarantee or warrantee expressed or
|
|||
|
// implied.
|
|||
|
//
|
|||
|
// version: 1.2
|
|||
|
//
|
|||
|
// email: mete@swissquake.ch
|
|||
|
// web: http://www.swissquake.ch/chumbalum-soft/
|
|||
|
//
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <string.h>
|
|||
|
#include <mx.h>
|
|||
|
#include <gl.h>
|
|||
|
#include <mxTga.h>
|
|||
|
#include "mdlviewer.h"
|
|||
|
#include "GlWindow.h"
|
|||
|
#include "ControlPanel.h"
|
|||
|
#include "StudioModel.h"
|
|||
|
#include "pakviewer.h"
|
|||
|
#include "FileAssociation.h"
|
|||
|
#include "stringlib.h"
|
|||
|
|
|||
|
MDLViewer *g_MDLViewer = 0;
|
|||
|
char g_appTitle[] = "Paranoia 2 Model Viewer v1.31 stable";
|
|||
|
static char recentFiles[8][256] = { "", "", "", "", "", "", "", "" };
|
|||
|
extern bool bUseWeaponOrigin;
|
|||
|
extern bool bUseWeaponLeftHand;
|
|||
|
|
|||
|
void MDLViewer::initRecentFiles( void )
|
|||
|
{
|
|||
|
for (int i = 0; i < 8; i++)
|
|||
|
{
|
|||
|
if (strlen (recentFiles[i]))
|
|||
|
{
|
|||
|
mb->modify (IDC_FILE_RECENTMODELS1 + i, IDC_FILE_RECENTMODELS1 + i, recentFiles[i]);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
mb->modify (IDC_FILE_RECENTMODELS1 + i, IDC_FILE_RECENTMODELS1 + i, "(empty)");
|
|||
|
mb->setEnabled (IDC_FILE_RECENTMODELS1 + i, false);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void MDLViewer::loadRecentFiles( void )
|
|||
|
{
|
|||
|
char str[256];
|
|||
|
|
|||
|
for( int i = 0; i < 8; i++ )
|
|||
|
{
|
|||
|
mx_snprintf( str, sizeof( str ), "RecentFile%i", i );
|
|||
|
if( !LoadString( str, recentFiles[i] ))
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void MDLViewer::saveRecentFiles( void )
|
|||
|
{
|
|||
|
char str[256];
|
|||
|
|
|||
|
if( !InitRegistry( ))
|
|||
|
return;
|
|||
|
|
|||
|
for( int i = 0; i < 8; i++ )
|
|||
|
{
|
|||
|
mx_snprintf( str, sizeof( str ), "RecentFile%i", i );
|
|||
|
if( !SaveString( str, recentFiles[i] ))
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
MDLViewer :: MDLViewer() : mxWindow( 0, 0, 0, 0, 0, g_appTitle, mxWindow::Normal )
|
|||
|
{
|
|||
|
// create menu stuff
|
|||
|
mb = new mxMenuBar (this);
|
|||
|
mxMenu *menuFile = new mxMenu ();
|
|||
|
mxMenu *menuOptions = new mxMenu ();
|
|||
|
mxMenu *menuView = new mxMenu ();
|
|||
|
mxMenu *menuHelp = new mxMenu ();
|
|||
|
|
|||
|
mb->addMenu ("File", menuFile);
|
|||
|
mb->addMenu ("Options", menuOptions);
|
|||
|
mb->addMenu ("Tools", menuView);
|
|||
|
mb->addMenu ("Help", menuHelp);
|
|||
|
|
|||
|
mxMenu *menuRecentModels = new mxMenu ();
|
|||
|
menuRecentModels->add ("(empty)", IDC_FILE_RECENTMODELS1);
|
|||
|
menuRecentModels->add ("(empty)", IDC_FILE_RECENTMODELS2);
|
|||
|
menuRecentModels->add ("(empty)", IDC_FILE_RECENTMODELS3);
|
|||
|
menuRecentModels->add ("(empty)", IDC_FILE_RECENTMODELS4);
|
|||
|
|
|||
|
mxMenu *menuRecentPakFiles = new mxMenu ();
|
|||
|
menuRecentPakFiles->add ("(empty)", IDC_FILE_RECENTPAKFILES1);
|
|||
|
menuRecentPakFiles->add ("(empty)", IDC_FILE_RECENTPAKFILES2);
|
|||
|
menuRecentPakFiles->add ("(empty)", IDC_FILE_RECENTPAKFILES3);
|
|||
|
menuRecentPakFiles->add ("(empty)", IDC_FILE_RECENTPAKFILES4);
|
|||
|
|
|||
|
menuFile->add ("Load Model...", IDC_FILE_LOADMODEL);
|
|||
|
menuFile->add ("Save Model...", IDC_FILE_SAVEMODEL);
|
|||
|
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->add ("Open PAK file...", IDC_FILE_OPENPAKFILE);
|
|||
|
menuFile->add ("Close PAK file", IDC_FILE_CLOSEPAKFILE);
|
|||
|
menuFile->addSeparator ();
|
|||
|
menuFile->addMenu ("Recent Models", menuRecentModels);
|
|||
|
menuFile->addMenu ("Recent PAK files", menuRecentPakFiles);
|
|||
|
menuFile->addSeparator ();
|
|||
|
menuFile->add ("Exit", IDC_FILE_EXIT);
|
|||
|
|
|||
|
menuOptions->add ("Background Color...", IDC_OPTIONS_COLORBACKGROUND);
|
|||
|
menuOptions->add ("Ground Color...", IDC_OPTIONS_COLORGROUND);
|
|||
|
menuOptions->add ("Light Color...", IDC_OPTIONS_COLORLIGHT);
|
|||
|
menuOptions->addSeparator ();
|
|||
|
menuOptions->add( "Sequence AutoPlay", IDC_OPTIONS_AUTOPLAY );
|
|||
|
menuOptions->add( "Using BoneWeights", IDC_OPTIONS_BLENDWEIGHTS );
|
|||
|
menuOptions->addSeparator ();
|
|||
|
menuOptions->add( "Use weapon origin", IDC_OPTIONS_WEAPONORIGIN );
|
|||
|
menuOptions->add( "Weapon left-handed", IDC_OPTIONS_LEFTHAND );
|
|||
|
menuOptions->addSeparator ();
|
|||
|
menuOptions->add ("Center View", IDC_OPTIONS_CENTERVIEW);
|
|||
|
menuOptions->add ("Reset View", IDC_OPTIONS_RESETVIEW);
|
|||
|
#ifdef WIN32
|
|||
|
menuOptions->addSeparator ();
|
|||
|
menuOptions->add ("Make Screenshot...", IDC_OPTIONS_MAKESCREENSHOT);
|
|||
|
//menuOptions->add ("Dump Model Info", IDC_OPTIONS_DUMP);
|
|||
|
#endif
|
|||
|
|
|||
|
menuView->add ("File Associations...", IDC_VIEW_FILEASSOCIATIONS);
|
|||
|
|
|||
|
#ifdef WIN32
|
|||
|
menuHelp->add ("Goto Homepage...", IDC_HELP_GOTOHOMEPAGE);
|
|||
|
menuHelp->addSeparator ();
|
|||
|
#endif
|
|||
|
menuHelp->add ("About...", IDC_HELP_ABOUT);
|
|||
|
|
|||
|
mb->setChecked( IDC_OPTIONS_WEAPONORIGIN, bUseWeaponOrigin );
|
|||
|
mb->setChecked( IDC_OPTIONS_LEFTHAND, bUseWeaponLeftHand );
|
|||
|
mb->setChecked( IDC_OPTIONS_AUTOPLAY, g_viewerSettings.sequence_autoplay ? true : false );
|
|||
|
mb->setChecked( IDC_OPTIONS_BLENDWEIGHTS, g_viewerSettings.studio_blendweights ? true : false );
|
|||
|
|
|||
|
// create the OpenGL window
|
|||
|
d_GlWindow = new GlWindow (this, 0, 0, 0, 0, "", mxWindow::Normal);
|
|||
|
#ifdef WIN32
|
|||
|
SetWindowLong ((HWND) d_GlWindow->getHandle (), GWL_EXSTYLE, WS_EX_CLIENTEDGE);
|
|||
|
#endif
|
|||
|
|
|||
|
d_cpl = new ControlPanel (this);
|
|||
|
d_cpl->setGlWindow (d_GlWindow);
|
|||
|
d_GlWindow->setControlPanel(d_cpl);
|
|||
|
g_GlWindow = d_GlWindow;
|
|||
|
|
|||
|
// finally create the pakviewer window
|
|||
|
d_PAKViewer = new PAKViewer (this);
|
|||
|
g_FileAssociation = new FileAssociation ();
|
|||
|
|
|||
|
loadRecentFiles ();
|
|||
|
initRecentFiles ();
|
|||
|
|
|||
|
setBounds (20, 20, 640, 540);
|
|||
|
setVisible (true);
|
|||
|
|
|||
|
if( g_viewerSettings.showGround )
|
|||
|
d_cpl->setShowGround (true);
|
|||
|
|
|||
|
if( g_viewerSettings.groundTexFile[0] )
|
|||
|
d_GlWindow->loadTexture( g_viewerSettings.groundTexFile, TEXTURE_GROUND );
|
|||
|
else d_GlWindow->loadTexture( NULL, TEXTURE_GROUND );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
MDLViewer::~MDLViewer ()
|
|||
|
{
|
|||
|
// grab some params in case that hasn't updates
|
|||
|
if( d_cpl )
|
|||
|
g_viewerSettings.editStep = d_cpl->getEditStep();
|
|||
|
g_viewerSettings.showMaximized = isMaximized();
|
|||
|
|
|||
|
saveRecentFiles ();
|
|||
|
SaveViewerSettings ();
|
|||
|
g_studioModel.FreeModel ();
|
|||
|
#ifdef WIN32
|
|||
|
DeleteFile ("midump.txt");
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
void MDLViewer :: checkboxSet( int id, bool bState )
|
|||
|
{
|
|||
|
mb->setChecked( id, bState );
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
MDLViewer::handleEvent (mxEvent *event)
|
|||
|
{
|
|||
|
switch (event->event)
|
|||
|
{
|
|||
|
case mxEvent::Action:
|
|||
|
{
|
|||
|
switch (event->action)
|
|||
|
{
|
|||
|
case IDC_FILE_LOADMODEL:
|
|||
|
{
|
|||
|
const char *ptr = mxGetOpenFileName (this, 0, "*.mdl");
|
|||
|
if (ptr)
|
|||
|
{
|
|||
|
int i;
|
|||
|
d_cpl->loadModel (ptr);
|
|||
|
|
|||
|
for (i = 0; i < 4; i++)
|
|||
|
{
|
|||
|
if (!mx_strcasecmp (recentFiles[i], ptr))
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
// swap existing recent file
|
|||
|
if (i < 4)
|
|||
|
{
|
|||
|
char tmp[256];
|
|||
|
strcpy (tmp, recentFiles[0]);
|
|||
|
strcpy (recentFiles[0], recentFiles[i]);
|
|||
|
strcpy (recentFiles[i], tmp);
|
|||
|
}
|
|||
|
|
|||
|
// insert recent file
|
|||
|
else
|
|||
|
{
|
|||
|
for (i = 3; i > 0; i--)
|
|||
|
strcpy (recentFiles[i], recentFiles[i - 1]);
|
|||
|
|
|||
|
strcpy (recentFiles[0], ptr);
|
|||
|
}
|
|||
|
|
|||
|
initRecentFiles ();
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_FILE_SAVEMODEL:
|
|||
|
{
|
|||
|
char *ptr = (char *) mxGetSaveFileName (this, g_viewerSettings.modelPath, "*.mdl", g_viewerSettings.modelPath);
|
|||
|
if (!ptr)
|
|||
|
break;
|
|||
|
|
|||
|
char filename[256];
|
|||
|
char ext[16];
|
|||
|
|
|||
|
strcpy( filename, ptr );
|
|||
|
strcpy( ext, mx_getextension( filename ));
|
|||
|
if( mx_strcasecmp( ext, ".mdl" ))
|
|||
|
strcat( filename, ".mdl" );
|
|||
|
|
|||
|
if( !g_studioModel.SaveModel( filename ))
|
|||
|
{
|
|||
|
mxMessageBox( this, "Error saving model.", g_appTitle, MX_MB_OK | MX_MB_ERROR );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
strcpy( g_viewerSettings.modelFile, filename );
|
|||
|
g_viewerSettings.numModelChanges = 0; // all the settings are handled
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_FILE_LOADBACKGROUNDTEX:
|
|||
|
case IDC_FILE_LOADGROUNDTEX:
|
|||
|
{
|
|||
|
const char *ptr = mxGetOpenFileName (this, 0, "*.bmp;*.tga;*.pcx");
|
|||
|
if (ptr)
|
|||
|
{
|
|||
|
int name = TEXTURE_UNUSED;
|
|||
|
|
|||
|
if( event->action == IDC_FILE_LOADBACKGROUNDTEX )
|
|||
|
name = TEXTURE_BACKGROUND;
|
|||
|
else if( event->action == IDC_FILE_LOADGROUNDTEX )
|
|||
|
name = TEXTURE_GROUND;
|
|||
|
|
|||
|
if (d_GlWindow->loadTexture( ptr, name ))
|
|||
|
{
|
|||
|
if (event->action == IDC_FILE_LOADBACKGROUNDTEX)
|
|||
|
d_cpl->setShowBackground (true);
|
|||
|
else
|
|||
|
d_cpl->setShowGround (true);
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
mxMessageBox (this, "Error loading texture.", g_appTitle, MX_MB_OK | MX_MB_ERROR);
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_FILE_UNLOADGROUNDTEX:
|
|||
|
{
|
|||
|
d_GlWindow->loadTexture( NULL, TEXTURE_GROUND );
|
|||
|
d_cpl->setShowGround (false);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_FILE_OPENPAKFILE:
|
|||
|
{
|
|||
|
const char *ptr = mxGetOpenFileName (this, "\\sierra\\half-life\\valve", "*.pak");
|
|||
|
if (ptr)
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
d_PAKViewer->openPAKFile (ptr);
|
|||
|
|
|||
|
for (i = 4; i < 8; i++)
|
|||
|
{
|
|||
|
if (!mx_strcasecmp (recentFiles[i], ptr))
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
// swap existing recent file
|
|||
|
if (i < 8)
|
|||
|
{
|
|||
|
char tmp[256];
|
|||
|
strcpy (tmp, recentFiles[4]);
|
|||
|
strcpy (recentFiles[4], recentFiles[i]);
|
|||
|
strcpy (recentFiles[i], tmp);
|
|||
|
}
|
|||
|
|
|||
|
// insert recent file
|
|||
|
else
|
|||
|
{
|
|||
|
for (i = 7; i > 4; i--)
|
|||
|
strcpy (recentFiles[i], recentFiles[i - 1]);
|
|||
|
|
|||
|
strcpy (recentFiles[4], ptr);
|
|||
|
}
|
|||
|
|
|||
|
initRecentFiles ();
|
|||
|
|
|||
|
redraw ();
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_FILE_CLOSEPAKFILE:
|
|||
|
{
|
|||
|
d_PAKViewer->closePAKFile ();
|
|||
|
redraw ();
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_FILE_RECENTMODELS1:
|
|||
|
case IDC_FILE_RECENTMODELS2:
|
|||
|
case IDC_FILE_RECENTMODELS3:
|
|||
|
case IDC_FILE_RECENTMODELS4:
|
|||
|
{
|
|||
|
int i = event->action - IDC_FILE_RECENTMODELS1;
|
|||
|
d_cpl->loadModel (recentFiles[i]);
|
|||
|
|
|||
|
char tmp[256];
|
|||
|
strcpy (tmp, recentFiles[0]);
|
|||
|
strcpy (recentFiles[0], recentFiles[i]);
|
|||
|
strcpy (recentFiles[i], tmp);
|
|||
|
|
|||
|
initRecentFiles ();
|
|||
|
|
|||
|
redraw ();
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_FILE_RECENTPAKFILES1:
|
|||
|
case IDC_FILE_RECENTPAKFILES2:
|
|||
|
case IDC_FILE_RECENTPAKFILES3:
|
|||
|
case IDC_FILE_RECENTPAKFILES4:
|
|||
|
{
|
|||
|
int i = event->action - IDC_FILE_RECENTPAKFILES1 + 4;
|
|||
|
d_PAKViewer->openPAKFile (recentFiles[i]);
|
|||
|
|
|||
|
char tmp[256];
|
|||
|
strcpy (tmp, recentFiles[4]);
|
|||
|
strcpy (recentFiles[4], recentFiles[i]);
|
|||
|
strcpy (recentFiles[i], tmp);
|
|||
|
|
|||
|
initRecentFiles ();
|
|||
|
|
|||
|
redraw ();
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_FILE_EXIT:
|
|||
|
{
|
|||
|
d_PAKViewer->closePAKFile ();
|
|||
|
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:
|
|||
|
d_cpl->centerView (false);
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_OPTIONS_RESETVIEW:
|
|||
|
d_cpl->centerView (true);
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_OPTIONS_MAKESCREENSHOT:
|
|||
|
{
|
|||
|
char *ptr = (char *)mxGetSaveFileName( this, "", "*.bmp" );
|
|||
|
if( ptr )
|
|||
|
{
|
|||
|
if( !strstr( ptr, ".bmp" ))
|
|||
|
strcat( ptr, ".bmp" );
|
|||
|
d_GlWindow->dumpViewport( ptr );
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_OPTIONS_WEAPONORIGIN:
|
|||
|
bUseWeaponOrigin = !mb->isChecked( IDC_OPTIONS_WEAPONORIGIN );
|
|||
|
mb->setChecked( IDC_OPTIONS_WEAPONORIGIN, bUseWeaponOrigin );
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_OPTIONS_LEFTHAND:
|
|||
|
bUseWeaponLeftHand = !mb->isChecked( IDC_OPTIONS_LEFTHAND );
|
|||
|
mb->setChecked( IDC_OPTIONS_LEFTHAND, bUseWeaponLeftHand );
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_OPTIONS_AUTOPLAY:
|
|||
|
g_viewerSettings.sequence_autoplay = !mb->isChecked( IDC_OPTIONS_AUTOPLAY );
|
|||
|
mb->setChecked( IDC_OPTIONS_AUTOPLAY, g_viewerSettings.sequence_autoplay ? true : false );
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_OPTIONS_BLENDWEIGHTS:
|
|||
|
g_viewerSettings.studio_blendweights = !mb->isChecked( IDC_OPTIONS_BLENDWEIGHTS );
|
|||
|
mb->setChecked( IDC_OPTIONS_BLENDWEIGHTS, g_viewerSettings.studio_blendweights ? true : false );
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_OPTIONS_DUMP:
|
|||
|
d_cpl->dumpModelInfo ();
|
|||
|
break;
|
|||
|
|
|||
|
case IDC_VIEW_FILEASSOCIATIONS:
|
|||
|
g_FileAssociation->setAssociation (0);
|
|||
|
g_FileAssociation->setVisible (true);
|
|||
|
break;
|
|||
|
|
|||
|
#ifdef WIN32
|
|||
|
case IDC_HELP_GOTOHOMEPAGE:
|
|||
|
ShellExecute (0, "open", "http://cs-mapping.com.ua/forum/forumdisplay.php?f=189", 0, 0, SW_SHOW);
|
|||
|
break;
|
|||
|
#endif
|
|||
|
|
|||
|
case IDC_HELP_ABOUT:
|
|||
|
mxMessageBox (this,
|
|||
|
"Paranoia 2 Model Viewer v1.31 (c) 2019 by Unkle Mike\n"
|
|||
|
"Based on original HLMV code by Mete Ciragan\n\n"
|
|||
|
"Left-drag to rotate.\n"
|
|||
|
"Right-drag to zoom.\n"
|
|||
|
"Shift-left-drag to x-y-pan.\n"
|
|||
|
"Ctrl-drag to move lights.\n\n"
|
|||
|
"Build:\t" __DATE__ ".\n"
|
|||
|
"Email:\tg-cont@rambler.ru\n"
|
|||
|
"Web:\thttp://www.hlfx.ru/forum", "About Paranoia 2 Model Viewer",
|
|||
|
MX_MB_OK | MX_MB_INFORMATION );
|
|||
|
break;
|
|||
|
|
|||
|
} //switch (event->action)
|
|||
|
|
|||
|
} // mxEvent::Action
|
|||
|
break;
|
|||
|
|
|||
|
case mxEvent::Size:
|
|||
|
{
|
|||
|
int w = event->width;
|
|||
|
int h = event->height;
|
|||
|
int y = mb->getHeight ();
|
|||
|
#ifdef WIN32
|
|||
|
#define HEIGHT 120
|
|||
|
#else
|
|||
|
#define HEIGHT 140
|
|||
|
h -= 40;
|
|||
|
#endif
|
|||
|
|
|||
|
if (d_PAKViewer->isVisible ())
|
|||
|
{
|
|||
|
w -= 170;
|
|||
|
d_PAKViewer->setBounds (w, y, 170, h);
|
|||
|
}
|
|||
|
|
|||
|
d_GlWindow->setBounds (0, y, w, h - HEIGHT);
|
|||
|
d_cpl->setBounds (0, y + h - HEIGHT, w, HEIGHT);
|
|||
|
}
|
|||
|
break;
|
|||
|
case mxEvent::KeyDown:
|
|||
|
{
|
|||
|
switch( (char)event->key )
|
|||
|
{
|
|||
|
case 32:
|
|||
|
{
|
|||
|
static float lasttime = 0.0f;
|
|||
|
|
|||
|
if( lasttime > g_studioModel.getCurrentTime( ))
|
|||
|
break;
|
|||
|
lasttime = g_studioModel.getCurrentTime() + 0.1f;
|
|||
|
|
|||
|
int iSeq = g_studioModel.GetSequence();
|
|||
|
|
|||
|
if( iSeq == g_studioModel.SetSequence( iSeq + 1 ))
|
|||
|
g_studioModel.SetSequence( 0 );
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 27:
|
|||
|
if( !getParent( )) // fullscreen mode ?
|
|||
|
mx::quit();
|
|||
|
break;
|
|||
|
case 37:
|
|||
|
if( g_viewerSettings.numModelPathes > 0 )
|
|||
|
d_cpl->loadModel( LoadPrevModel( ));
|
|||
|
break;
|
|||
|
case 39:
|
|||
|
if( g_viewerSettings.numModelPathes > 0 )
|
|||
|
d_cpl->loadModel( LoadNextModel( ));
|
|||
|
break;
|
|||
|
case VK_F5:
|
|||
|
{
|
|||
|
bool oldUseWeaponOrigin = bUseWeaponOrigin;
|
|||
|
d_cpl->loadModel( g_viewerSettings.modelFile, false );
|
|||
|
bUseWeaponOrigin = oldUseWeaponOrigin;
|
|||
|
break;
|
|||
|
}
|
|||
|
case 'g':
|
|||
|
case '<EFBFBD>':
|
|||
|
g_viewerSettings.showGround = !g_viewerSettings.showGround;
|
|||
|
if( !g_viewerSettings.showGround )
|
|||
|
g_viewerSettings.mirror = false;
|
|||
|
break;
|
|||
|
case 'h':
|
|||
|
case '<EFBFBD>':
|
|||
|
g_viewerSettings.showHitBoxes = !g_viewerSettings.showHitBoxes;
|
|||
|
break;
|
|||
|
case 'o':
|
|||
|
case '<EFBFBD>':
|
|||
|
g_viewerSettings.showBones = !g_viewerSettings.showBones;
|
|||
|
break;
|
|||
|
case '5':
|
|||
|
g_viewerSettings.transparency -= 0.05f;
|
|||
|
if( g_viewerSettings.transparency < 0.0f )
|
|||
|
g_viewerSettings.transparency = 0.0f;
|
|||
|
break;
|
|||
|
case '6':
|
|||
|
g_viewerSettings.transparency += 0.05f;
|
|||
|
if( g_viewerSettings.transparency > 1.0f )
|
|||
|
g_viewerSettings.transparency = 1.0f;
|
|||
|
break;
|
|||
|
case 'b':
|
|||
|
case '<EFBFBD>':
|
|||
|
g_viewerSettings.showBackground = !g_viewerSettings.showBackground;
|
|||
|
break;
|
|||
|
case 's':
|
|||
|
case '<EFBFBD>':
|
|||
|
g_viewerSettings.useStencil = !g_viewerSettings.useStencil;
|
|||
|
break;
|
|||
|
case 'm':
|
|||
|
case '<EFBFBD>':
|
|||
|
g_viewerSettings.mirror = !g_viewerSettings.mirror;
|
|||
|
if( g_viewerSettings.mirror )
|
|||
|
g_viewerSettings.showGround = true;
|
|||
|
break;
|
|||
|
case 'v':
|
|||
|
case '<EFBFBD>':
|
|||
|
bUseWeaponOrigin = !mb->isChecked( IDC_OPTIONS_WEAPONORIGIN );
|
|||
|
mb->setChecked( IDC_OPTIONS_WEAPONORIGIN, bUseWeaponOrigin );
|
|||
|
break;
|
|||
|
case 'l':
|
|||
|
case '<EFBFBD>':
|
|||
|
bUseWeaponLeftHand = !mb->isChecked( IDC_OPTIONS_LEFTHAND );
|
|||
|
mb->setChecked( IDC_OPTIONS_LEFTHAND, bUseWeaponLeftHand );
|
|||
|
break;
|
|||
|
|
|||
|
case 'w':
|
|||
|
case '<EFBFBD>':
|
|||
|
g_viewerSettings.studio_blendweights = !mb->isChecked( IDC_OPTIONS_BLENDWEIGHTS );
|
|||
|
mb->setChecked( IDC_OPTIONS_BLENDWEIGHTS, g_viewerSettings.studio_blendweights ? true : false );
|
|||
|
break;
|
|||
|
case '1':
|
|||
|
case '2':
|
|||
|
case '3':
|
|||
|
case '4':
|
|||
|
g_viewerSettings.renderMode = event->key - '1';
|
|||
|
break;
|
|||
|
case '-':
|
|||
|
g_viewerSettings.speedScale -= 0.1f;
|
|||
|
if( g_viewerSettings.speedScale < 0.0f )
|
|||
|
g_viewerSettings.speedScale = 0.0f;
|
|||
|
break;
|
|||
|
case '+':
|
|||
|
g_viewerSettings.speedScale += 0.1f;
|
|||
|
if( g_viewerSettings.speedScale > 5.0f )
|
|||
|
g_viewerSettings.speedScale = 5.0f;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
} // event->event
|
|||
|
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
MDLViewer::redraw ()
|
|||
|
{
|
|||
|
mxEvent event;
|
|||
|
event.event = mxEvent::Size;
|
|||
|
event.width = w2 ();
|
|||
|
event.height = h2 ();
|
|||
|
handleEvent (&event);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
int main( int argc, char *argv[] )
|
|||
|
{
|
|||
|
//
|
|||
|
// make sure, we start in the right directory
|
|||
|
//
|
|||
|
mx_setcwd (mx::getApplicationPath ());
|
|||
|
atexit( Sys_CloseLog );
|
|||
|
|
|||
|
char cmdline[1024] = "";
|
|||
|
if (argc > 1)
|
|||
|
{
|
|||
|
strcpy (cmdline, argv[1]);
|
|||
|
for (int i = 2; i < argc; i++)
|
|||
|
{
|
|||
|
strcat (cmdline, " ");
|
|||
|
strcat (cmdline, argv[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if( IsAliasModel( cmdline ) && COM_FileExists( "q1mv.exe" ))
|
|||
|
{
|
|||
|
strcpy (cmdline, "q1mv.exe" );
|
|||
|
for (int i = 1; i < argc; i++)
|
|||
|
{
|
|||
|
strcat (cmdline, " ");
|
|||
|
strcat (cmdline, argv[i]);
|
|||
|
}
|
|||
|
WinExec (cmdline, SW_SHOW);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
LoadViewerSettings();
|
|||
|
|
|||
|
//mx::setDisplayMode (0, 0, 0);
|
|||
|
mx::init (argc, argv);
|
|||
|
g_MDLViewer = new MDLViewer ();
|
|||
|
g_MDLViewer->setMenuBar (g_MDLViewer->getMenuBar ());
|
|||
|
g_MDLViewer->setBounds (20, 20, 640, 540);
|
|||
|
g_MDLViewer->setVisible (true);
|
|||
|
|
|||
|
if( g_viewerSettings.showMaximized )
|
|||
|
g_MDLViewer->Maximize();
|
|||
|
|
|||
|
if (Q_stristr (cmdline, ".mdl"))
|
|||
|
{
|
|||
|
g_ControlPanel->loadModel (cmdline);
|
|||
|
}
|
|||
|
|
|||
|
int ret = mx::run ();
|
|||
|
|
|||
|
mx::cleanup ();
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|