summaryrefslogtreecommitdiff
path: root/vgui2/matsys_controls/QCGenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vgui2/matsys_controls/QCGenerator.cpp')
-rw-r--r--vgui2/matsys_controls/QCGenerator.cpp723
1 files changed, 723 insertions, 0 deletions
diff --git a/vgui2/matsys_controls/QCGenerator.cpp b/vgui2/matsys_controls/QCGenerator.cpp
new file mode 100644
index 0000000..89f0173
--- /dev/null
+++ b/vgui2/matsys_controls/QCGenerator.cpp
@@ -0,0 +1,723 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#if defined(WIN32) && !defined( _X360 )
+#include <windows.h>
+#endif
+#include "filesystem.h"
+#include "filesystem_init.h"
+#include "appframework/IAppSystemGroup.h"
+#include "appframework/IAppSystem.h"
+#include "appframework/AppFramework.h"
+#include "filesystem_helpers.h"
+
+#include "matsys_controls/QCGenerator.h"
+#include "tier1/KeyValues.h"
+#include "tier2/vconfig.h"
+#include "vgui_controls/ListPanel.h"
+#include "vgui_controls/TextEntry.h"
+#include "vgui_controls/Button.h"
+#include "vgui_controls/FileOpenDialog.h"
+#include "vgui_controls/DirectorySelectDialog.h"
+#include "vgui_controls/ComboBox.h"
+#include "vgui_controls/CheckButton.h"
+#include "vgui_controls/MessageBox.h"
+#include "vgui/ISurface.h"
+#include "vgui/IInput.h"
+#include "vgui/Cursor.h"
+#include "vgui_controls/KeyBoardEditorDialog.h"
+
+#if defined( _X360 )
+#include "xbox/xbox_win32stubs.h"
+#endif
+
+using namespace vgui;
+
+#define MAX_KEYVALUE 1024
+
+
+//-----------------------------------------------------------------------------
+// Purpose: returns a pointer to the 'count' occurence of a character from the end of a string
+// returns 0 of there aren't 'count' number of the character in the string
+//-----------------------------------------------------------------------------
+char *strrchrcount(char *string, int character, int count )
+{
+ int j = count;
+ int numChars = strlen( string );
+ for( int i = numChars; i > 0; i-- )
+ {
+ if( string[i-1] == character )
+ {
+ j--;
+ }
+ if( j == 0 )
+ {
+ return string + i-1;
+ }
+ }
+ return 0;
+}
+
+
+
+class CModalPreserveMessageBox : public vgui::MessageBox
+{
+public:
+ CModalPreserveMessageBox(const char *title, const char *text, vgui::Panel *parent)
+ : vgui::MessageBox( title, text, parent )
+ {
+ m_PrevAppFocusPanel = vgui::input()->GetAppModalSurface();
+ }
+
+ ~CModalPreserveMessageBox()
+ {
+ vgui::input()->SetAppModalSurface( m_PrevAppFocusPanel );
+ }
+
+
+public:
+ vgui::VPANEL m_PrevAppFocusPanel;
+};
+
+void VGUIMessageBox( vgui::Panel *pParent, const char *pTitle, const char *pMsg, ... )
+{
+ char msg[4096];
+ va_list marker;
+ va_start( marker, pMsg );
+ Q_vsnprintf( msg, sizeof( msg ), pMsg, marker );
+ va_end( marker );
+
+ vgui::MessageBox *dlg = new CModalPreserveMessageBox( pTitle, msg, pParent );
+ dlg->DoModal();
+ dlg->Activate();
+ dlg->RequestFocus();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Places all the info from the vgui controls into the QCInfo struct
+//-----------------------------------------------------------------------------
+void QCInfo::SyncFromControls()
+{
+ char tempText[MAX_PATH];
+
+ vgui::Panel *pTargetField = pQCGenerator->FindChildByName( "staticPropCheck" );
+ bStaticProp = ((CheckButton *)pTargetField)->IsSelected();
+
+ pTargetField = pQCGenerator->FindChildByName( "mostlyOpaqueCheck" );
+ bMostlyOpaque = ((CheckButton *)pTargetField)->IsSelected();
+
+ pTargetField = pQCGenerator->FindChildByName( "disableCollisionsCheck" );
+ bDisableCollision = ((CheckButton *)pTargetField)->IsSelected();
+
+ pTargetField = pQCGenerator->FindChildByName( "referencePhysicsCheck" );
+ bReferenceAsPhys = ((CheckButton *)pTargetField)->IsSelected();
+
+ pTargetField = pQCGenerator->FindChildByName( "concaveCheck" );
+ bConcave = ((CheckButton *)pTargetField)->IsSelected();
+
+ pTargetField = pQCGenerator->FindChildByName( "automassCheck" );
+ bAutomass = ((CheckButton *)pTargetField)->IsSelected();
+
+ pTargetField = pQCGenerator->FindChildByName( "massField" );
+ ((TextEntry *)pTargetField)->GetText(tempText, MAX_PATH);
+ fMass = atof(tempText);
+
+ pTargetField = pQCGenerator->FindChildByName( "scaleField" );
+ ((TextEntry *)pTargetField)->GetText(tempText, MAX_PATH);
+ fScale = atof(tempText);
+
+ pTargetField = pQCGenerator->FindChildByName( "collisionSMDField" );
+ ((TextEntry *)pTargetField)->GetText( tempText, MAX_PATH );
+ V_strcpy_safe( pszCollisionPath, tempText );
+
+ pTargetField = pQCGenerator->FindChildByName( "surfacePropertyDropDown" );
+ ((ComboBox *)pTargetField)->GetText( tempText, MAX_PATH );
+ V_strcpy_safe( pszSurfaceProperty, tempText );
+
+ pTargetField = pQCGenerator->FindChildByName( "materialsField" );
+ ((TextEntry *)pTargetField)->GetText( tempText, MAX_PATH );
+ V_strcpy_safe( pszMaterialPath, tempText );
+
+ LODs.RemoveAll();
+ pTargetField = pQCGenerator->FindChildByName( "LODList" );
+ int numLOD = ((ListPanel *)pTargetField)->GetItemCount();
+ for ( int i = 0; i < numLOD; i++ )
+ {
+ KeyValues *key = ((ListPanel *)pTargetField)->GetItem( i );
+ LODInfo newLOD;
+
+ V_strcpy_safe( newLOD.pszFilename, key->GetString( "SMD" ) );
+ newLOD.iLOD = key->GetInt( "LOD" );
+ LODs.AddToTail( newLOD );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Called during intialization to setup the initial state of the VGUI controls
+//-----------------------------------------------------------------------------
+void QCInfo::SyncToControls()
+{
+ char tempText[MAX_PATH];
+
+ vgui::Panel *pTargetField = pQCGenerator->FindChildByName( "staticPropCheck" );
+ ((CheckButton *)pTargetField)->SetSelected( bStaticProp );
+
+ pTargetField = pQCGenerator->FindChildByName( "mostlyOpaqueCheck" );
+ ((CheckButton *)pTargetField)->SetSelected( bMostlyOpaque );
+
+ pTargetField = pQCGenerator->FindChildByName( "disableCollisionsCheck" );
+ ((CheckButton *)pTargetField)->SetSelected( bDisableCollision );
+
+ pTargetField = pQCGenerator->FindChildByName( "referencePhysicsCheck" );
+ ((CheckButton *)pTargetField)->SetSelected( bReferenceAsPhys );
+
+ pTargetField = pQCGenerator->FindChildByName( "concaveCheck" );
+ ((CheckButton *)pTargetField)->SetSelected( bConcave );
+
+ pTargetField = pQCGenerator->FindChildByName( "automassCheck" );
+ ((CheckButton *)pTargetField)->SetSelected( bAutomass );
+
+ Q_snprintf( tempText, 10, "%d", (int)fMass );
+ pTargetField = pQCGenerator->FindChildByName( "massField" );
+ ((TextEntry *)pTargetField)->SetText( tempText );
+
+ Q_snprintf( tempText, 10, "%d", (int)fScale );
+ pTargetField = pQCGenerator->FindChildByName( "scaleField" );
+ ((TextEntry *)pTargetField)->SetText( tempText );
+
+ pTargetField = pQCGenerator->FindChildByName( "collisionSMDField" );
+ ((TextEntry *)pTargetField)->SetText( pszCollisionPath );
+
+ pTargetField = pQCGenerator->FindChildByName( "materialsField" );
+ ((TextEntry *)pTargetField)->SetText( pszMaterialPath );
+
+ pTargetField = pQCGenerator->FindChildByName( "surfacePropertyDropDown" );
+ int numItems = ((ComboBox *)pTargetField)->GetItemCount();
+ for( int i = 0; i < numItems; i++ )
+ {
+ ((ComboBox *)pTargetField)->GetItemText( i, tempText, MAX_PATH );
+ if ( !Q_strcmp( tempText, pszSurfaceProperty ) )
+ {
+ ((ComboBox *)pTargetField)->SetItemEnabled( i, true );
+ ((ComboBox *)pTargetField)->SetText( tempText );
+ break;
+ }
+ }
+}
+
+CBrowseButton::CBrowseButton( vgui::Panel *pParent ) : BaseClass( pParent, "Browse Button", "...", pParent, "browse" )
+{
+ SetParent( pParent );
+ pszStartingDirectory = NULL;
+ pszFileFilter = NULL;
+ pszTargetField = NULL;
+}
+
+CBrowseButton::~CBrowseButton()
+{
+}
+
+void CBrowseButton::SetCharVar( char **pVar, const char *pszNewText )
+{
+ if ( *pVar && pszNewText && !Q_strcmp( *pVar, pszNewText ) )
+ {
+ return;
+ }
+
+ if ( *pVar )
+ {
+ delete [] *pVar;
+ *pVar = NULL;
+ }
+
+ if ( pszNewText )
+ {
+ int len = Q_strlen( pszNewText ) + 1;
+ *pVar = new char[ len ];
+ Q_strncpy( *pVar, pszNewText, len );
+ }
+}
+
+void CBrowseButton::InitBrowseInfo( int x, int y, const char *pszName, const char *pszDir, const char *pszFilter, const char *pszField )
+{
+ SetSize( 24, 24 );
+ SetPos( x, y );
+ SetName( pszName );
+ SetCharVar( GetStartingDirectory(), pszDir );
+ SetCharVar( GetFileFilter(), pszFilter );
+ SetCharVar( GetTargetField(), pszField );
+ SetActionMessage();
+}
+
+void CBrowseButton::SetActionMessage()
+{
+ KeyValues *newActionMessage = new KeyValues( "browse", "directory", pszStartingDirectory, "filter", pszFileFilter);
+ newActionMessage->SetString( "targetField", pszTargetField );
+ SetCommand( newActionMessage );
+}
+
+const char *ParseKeyvalue( const char *pBuffer, char *key, char *value )
+{
+ char com_token[1024];
+
+ pBuffer = (const char *)ParseFile( pBuffer, com_token, NULL );
+ if ( Q_strlen( com_token ) < MAX_KEYVALUE )
+ {
+ Q_strncpy( key, com_token, MAX_KEYVALUE );
+ Q_strlower( key );
+ }
+ // no value on a close brace
+ if ( !Q_strcmp( key, "}" ) )
+ {
+ value[0] = 0;
+ return pBuffer;
+ }
+
+ pBuffer = (const char *)ParseFile( pBuffer, com_token, NULL );
+ if ( Q_strlen( com_token ) < MAX_KEYVALUE )
+ {
+ Q_strncpy( value, com_token, MAX_KEYVALUE );
+ Q_strlower( value );
+ }
+
+ return pBuffer;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CQCGenerator::CQCGenerator( vgui::Panel *pParent, const char *pszPath, const char *pszScene ) : BaseClass( pParent, "QCGenerator" )
+{
+ m_QCInfo_t.Init( this );
+
+ SetMinimumSize(846, 770);
+
+ m_pLODPanel = new ListPanel(this, "LODList");
+ m_pLODPanel->SetSelectIndividualCells( true );
+ m_pLODPanel->AddColumnHeader(0, "SMD", "LOD SMD", 450, 0);
+ m_pLODPanel->AddColumnHeader(1, "LOD", "LOD Distance", 50, 0);
+ m_pLODPanel->AddActionSignalTarget( this );
+ m_pLODPanel->SetMouseInputEnabled( true );
+
+ LoadControlSettings( "QCGenerator.res" );
+
+ m_pCollisionBrowseButton = new CBrowseButton( this );
+ m_pCollisionBrowseButton->InitBrowseInfo( 808, 158, "collisionBrowseButton", pszPath, "*.smd", "collisionSMDField" );
+
+ char szTerminatedPath[1024] = "\0";
+ sprintf( szTerminatedPath, "%s\\", pszPath );
+
+ InitializeSMDPaths( szTerminatedPath, pszScene );
+
+ char *pszMaterialsStart = strrchrcount( szTerminatedPath, '\\', 3 ) + 1;
+ char *pszMaterialsEnd = strrchr( szTerminatedPath, '\\');
+ Q_strncpy( m_QCInfo_t.pszMaterialPath, pszMaterialsStart, pszMaterialsEnd - pszMaterialsStart + 1 );
+
+ SetParent( pParent );
+
+ char szGamePath[1024] = "\0";
+ char szSearchPath[1024] = "\0";
+
+ // Get the currently set game configuration
+ GetVConfigRegistrySetting( GAMEDIR_TOKEN, szGamePath, sizeof( szGamePath ) );
+ static const char *pSurfacePropFilename = "\\scripts\\surfaceproperties.txt";
+
+ sprintf( szSearchPath, "%s%s", szGamePath, pSurfacePropFilename );
+
+ FileHandle_t fp = g_pFullFileSystem->Open( szSearchPath, "rb" );
+
+ if ( !fp )
+ {
+ //the set game configuration didn't have a surfaceproperties file; we are grabbing it from hl2
+ //TODO: This only works if they are in a subdirectory that is a peer to an hl2 directory
+ // that contains the file. It potentially needs to search the entire drive or prompt for the location
+ char *pszEndGamePath = Q_strrchr( szGamePath, '\\' );
+ pszEndGamePath[0] = 0;
+ V_strcat_safe( szGamePath, "\\hl2" );
+ sprintf( szSearchPath, "%s%s", szGamePath, pSurfacePropFilename );
+ fp = g_pFullFileSystem->Open( szSearchPath, "rb" );
+ }
+
+ int len = g_pFullFileSystem->Size( fp );
+
+ const char *szSurfacePropContents = new char[len+1];
+ g_pFullFileSystem->Read( (void *)szSurfacePropContents, len, fp );
+
+ char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
+
+ vgui::Panel *pSurfacePropDropDown = FindChildByName( "surfacePropertyDropDown" );
+
+ //filling up the surface property dropdown
+ while ( szSurfacePropContents )
+ {
+ szSurfacePropContents = ParseKeyvalue( szSurfacePropContents, key, value );
+ ((ComboBox *)pSurfacePropDropDown)->AddItem( key, NULL );
+ while ( szSurfacePropContents )
+ {
+ szSurfacePropContents = ParseKeyvalue( szSurfacePropContents, key, value );
+ if (!stricmp( key, "}" ) )
+ {
+ break;
+ }
+ }
+ }
+ m_QCInfo_t.SyncToControls();
+
+ m_pLODEdit = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+CQCGenerator::~CQCGenerator()
+{
+}
+
+void CQCGenerator::OnCommand( const char *command )
+{
+ if ( Q_stricmp( command, "createQC" ) == 0 )
+ {
+ m_QCInfo_t.SyncFromControls();
+ GenerateQCFile();
+ }
+ if ( Q_stricmp( command, "deleteSeq" ) == 0 )
+ {
+ //delete it
+ DeleteLOD();
+ }
+ if ( Q_stricmp( command, "editSeq" ) == 0 )
+ {
+ //edit
+ EditLOD();
+ }
+
+ BaseClass::OnCommand( command );
+}
+
+
+void CQCGenerator::OnKeyCodeTyped( KeyCode code )
+{
+ switch ( code )
+ {
+ case KEY_ENTER:
+ EditLOD();
+ }
+}
+
+
+void CQCGenerator::OnBrowse( KeyValues *data )
+{
+ V_strcpy_safe( m_szTargetField, data->GetString( "targetField" ) );
+ const char *filter = data->GetString( "filter" );
+
+ if ( Q_strlen( filter ) == 0 )
+ {
+// BrowseDirectory( data );
+ }
+ else
+ {
+ BrowseFile( data );
+ }
+}
+
+/*
+//This function is no longer used in the current version of the program.
+void CQCGenerator::BrowseDirectory( KeyValues *data )
+{
+ DirectorySelectDialog *pDialog = new DirectorySelectDialog( this, "Select Directory" );
+ pDialog->AddActionSignalTarget( this );
+ pDialog->DoModal();
+ pDialog->SetStartDirectory( data->GetString( "directory" ) );
+}
+*/
+
+void CQCGenerator::BrowseFile( KeyValues *data )
+{
+ const char *filter = data->GetString( "filter" );
+
+ FileOpenDialog *pDialog = new FileOpenDialog( this, "Select File", true );
+ pDialog->AddFilter( filter, filter, true );
+ pDialog->AddActionSignalTarget(this);
+ pDialog->SetStartDirectory( data->GetString( "directory" ) );
+ pDialog->DoModal( true );
+}
+
+void CQCGenerator::OnFileSelected( KeyValues *data )
+{
+ if ( m_szTargetField )
+ {
+ vgui::Panel *pTargetField = FindChildByName( m_szTargetField );
+ ((TextEntry *)pTargetField)->SetText( data->GetString( "fullpath" ) );
+ Repaint();
+ }
+}
+
+void CQCGenerator::OnDirectorySelected( KeyValues *data )
+{
+ if ( m_szTargetField )
+ {
+ vgui::Panel *pTargetField = FindChildByName( m_szTargetField );
+ ((TextEntry *)pTargetField)->SetText( data->GetString( "dir" ) );
+ Repaint();
+ }
+}
+
+bool CQCGenerator::GenerateQCFile()
+{
+ //TODO: clean this up. Consider creating a datatype that includes the string to write out when the QC file is created
+ char *nameBegin = strrchr( m_QCInfo_t.pszSMDPath, '\\' );
+
+ char szPath[MAX_PATH];
+ char szName[MAX_PATH];
+ Q_strncpy( szPath, m_QCInfo_t.pszSMDPath, nameBegin - m_QCInfo_t.pszSMDPath + 2 );
+ V_strcpy_safe( szName, szPath);
+ V_strcat_safe( szName, m_QCInfo_t.pszSceneName);
+ V_strcat_safe( szName, ".qc" );
+ FileHandle_t pSaveFile = g_pFullFileSystem->Open( szName, "wt" );
+ if (!pSaveFile)
+ {
+ char szSaveError[1024] = "";
+ Q_snprintf( szSaveError, 1024, "Save failed: invalid file name '%s'\n\nDirectory '%s' must exist.", szName, szPath );
+ VGUIMessageBox( this, "QC Generator error", szSaveError );
+ return 0;
+ }
+
+ //write qc header
+ g_pFullFileSystem->FPrintf( pSaveFile, "//\n// .qc file version 1.0\n\n");
+ //write out modelname info
+ char szModelName[MAX_PATH];
+ char *modelStart = strrchrcount( szName, '\\', 2) + 1;
+ char *modelEnd = strrchr( szName, '.' );
+ Q_strncpy( szModelName, modelStart, modelEnd - modelStart + 1 );
+ V_strcat_safe( szModelName, ".mdl" );
+ g_pFullFileSystem->FPrintf( pSaveFile, "$modelname %s\n\n", szModelName );
+ //write out scale info
+ g_pFullFileSystem->FPrintf( pSaveFile, "$scale %f\n", m_QCInfo_t.fScale );
+ //write out body info
+ g_pFullFileSystem->FPrintf( pSaveFile, "$body \"Body\" \"%s\"\n", strrchr( m_QCInfo_t.pszSMDPath, '\\' ) + 1 );
+
+ if ( m_QCInfo_t.bStaticProp == true )
+ {
+ g_pFullFileSystem->FPrintf( pSaveFile, "$staticprop\n" );
+ }
+
+ if ( m_QCInfo_t.bMostlyOpaque == true )
+ {
+ g_pFullFileSystem->FPrintf( pSaveFile, "$mostlyopaque\n" );
+ }
+
+ //write out surfaceprop info
+ g_pFullFileSystem->FPrintf( pSaveFile, "$surfaceprop \"%s\"\n\n", m_QCInfo_t.pszSurfaceProperty );
+ //write materials
+
+ g_pFullFileSystem->FPrintf( pSaveFile, "$cdmaterials %s\n\n", m_QCInfo_t.pszMaterialPath);
+
+ if ( m_QCInfo_t.bStaticProp || m_QCInfo_t.bNoAnimation )
+ {
+ g_pFullFileSystem->FPrintf( pSaveFile, "// --------- Animation sequences -------\n");
+ g_pFullFileSystem->FPrintf( pSaveFile, "$sequence \"idle\" \"%s\" fps 30\n\n", strrchr(m_QCInfo_t.pszSMDPath, '\\')+1);
+ }
+
+ //write out lod info
+ for( int i = 0; i < m_QCInfo_t.LODs.Count(); i++ )
+ {
+ LODInfo thisLOD = m_QCInfo_t.LODs.Element( i );
+ g_pFullFileSystem->FPrintf( pSaveFile, "$lod %d\n{\n\treplacemodel \"%s\" \"%s\"\n}\n\n", thisLOD.iLOD, strrchr(m_QCInfo_t.pszSMDPath, '\\')+1, thisLOD.pszFilename );
+ }
+
+ if ( m_QCInfo_t.bDisableCollision != true )
+ {
+ //write out collision header
+ g_pFullFileSystem->FPrintf( pSaveFile, "\n" );
+ //write out collision info
+ if ( m_QCInfo_t.bReferenceAsPhys == true )
+ {
+ g_pFullFileSystem->FPrintf( pSaveFile, "$collisionmodel \"%s\"", strrchr( m_QCInfo_t.pszSMDPath, '\\' ) + 1 );
+ }
+ else
+ {
+ if( Q_strcmp( m_QCInfo_t.pszCollisionPath, "" ) )
+ {
+ g_pFullFileSystem->FPrintf( pSaveFile, "$collisionmodel \"%s\"", strrchr( m_QCInfo_t.pszCollisionPath, '\\' ) + 1 );
+ }
+ }
+
+ g_pFullFileSystem->FPrintf( pSaveFile, " {\n\t// Mass in kilograms\n ");
+
+ if ( m_QCInfo_t.bAutomass == true )
+ {
+ g_pFullFileSystem->FPrintf( pSaveFile, "\t$automass\n" );
+ }
+ else
+ {
+ g_pFullFileSystem->FPrintf( pSaveFile, "\t$mass %f\n", m_QCInfo_t.fMass );
+ }
+
+ if ( m_QCInfo_t.bConcave == true )
+ {
+ g_pFullFileSystem->FPrintf( pSaveFile, "\t$concave\n" );
+ }
+ g_pFullFileSystem->FPrintf( pSaveFile, "}\n\n");
+ }
+
+ g_pFullFileSystem->Close( pSaveFile );
+
+ char szCommand[MAX_PATH];
+ char szGamePath[MAX_PATH];
+
+ char studiomdlPath[512];
+ g_pFullFileSystem->RelativePathToFullPath( "studiomdl.bat", NULL, studiomdlPath, sizeof( studiomdlPath ));
+
+ GetVConfigRegistrySetting( GAMEDIR_TOKEN, szGamePath, sizeof( szGamePath ) );
+
+#ifdef WIN32
+ STARTUPINFO startup;
+ PROCESS_INFORMATION process;
+
+
+ memset(&startup, 0, sizeof(startup));
+ startup.cb = sizeof(startup);
+
+
+ sprintf( szCommand, "%s -game %s %s", studiomdlPath, szGamePath, szName);
+ bool bReturn = CreateProcess( NULL, szCommand, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &startup, &process);
+#else
+ Assert( !"Implement me, why aren't we using a thread tool abstraction?" );
+ bool bReturn = false;
+#endif
+ return bReturn;
+}
+
+void CQCGenerator::InitializeSMDPaths( const char *pszPath, const char *pszScene )
+{
+ V_strcpy_safe( m_QCInfo_t.pszSceneName, pszScene );
+
+ FileFindHandle_t *pFileHandle = new FileFindHandle_t();
+
+ g_pFullFileSystem->AddSearchPath( pszPath, "SMD_DIR" );
+
+ const char *filename = g_pFullFileSystem->FindFirst( "*.smd", pFileHandle );
+
+ bool bFoundReference = false;
+ bool bFoundCollision = false;
+ bool bFoundLOD = false;
+
+ //iterate through .smd files
+ const char *startName = pszScene;
+
+ int nSearchLength = Q_strlen( pszScene );
+
+ int currentLOD = 1;
+
+ while( filename )
+ {
+ if ( !strncmp( startName, filename, nSearchLength ) )
+ {
+ const char *filenameEnd = filename + nSearchLength;
+ if ( !strncmp( filenameEnd, "_ref", 4 ) || !strncmp( filenameEnd, ".smd", 4 ) )
+ {
+ bFoundReference = true;
+ //we have found the reference smd.
+ V_strcpy_safe( m_QCInfo_t.pszSMDPath, pszPath );
+ V_strcat_safe( m_QCInfo_t.pszSMDPath, filename );
+ }
+ if ( !strncmp( filenameEnd, "_phy", 4) || !strncmp( filenameEnd, "_col", 4 ) )
+ {
+ bFoundCollision = true;
+ //we have found the collision smd.
+ V_strcpy_safe( m_QCInfo_t.pszCollisionPath, pszPath );
+ V_strcat_safe( m_QCInfo_t.pszCollisionPath, filename );
+ }
+ if ( !strncmp( filenameEnd, "_lod", 4) )
+ {
+ bFoundLOD = true;
+ //we found an LOD smd.
+ char lodName[255];
+ Q_snprintf( lodName, Q_strlen( lodName ), "lod%d", currentLOD );
+ //we found an LOD
+ KeyValues *newKv = new KeyValues( lodName, "SMD", filename, "LOD", "10" );
+ m_pLODPanel->AddItem( newKv, currentLOD, false, false );
+ currentLOD++;
+ }
+ }
+ filename = g_pFullFileSystem->FindNext( *pFileHandle );
+ }
+ char pszMessage[2048] = "";
+ char pszRefMessage[1024] = "";
+ char pszColMessage[1024] = "";
+ if (!bFoundReference )
+ {
+ V_strcat_safe( m_QCInfo_t.pszSMDPath, pszPath );
+ V_strcat_safe( m_QCInfo_t.pszSMDPath, pszScene );
+ V_strcat_safe( m_QCInfo_t.pszSMDPath, ".smd" );
+ Q_snprintf( pszRefMessage, 1024, "Reference SMD not found.\n\nValid default reference SMDs are %s%s_ref*.smd and %s%s.smd\nUsing default of %s. Model will not compile.\n\n", pszPath, pszScene, pszPath, pszScene, m_QCInfo_t.pszSMDPath );
+ }
+ if ( !bFoundCollision )
+ {
+ Q_snprintf( pszColMessage, 1024, "Collision SMD not found.\n\nThe valid default collision SMD is %s%s_phy*.smd.\nUsing reference SMD as default.\n", pszPath, pszScene );
+ V_strcpy_safe( m_QCInfo_t.pszCollisionPath, m_QCInfo_t.pszSMDPath );
+ m_QCInfo_t.bReferenceAsPhys = true;
+ }
+ if ( !bFoundReference || !bFoundCollision)
+ {
+ V_strcpy_safe( pszMessage, pszRefMessage );
+ V_strcat_safe( pszMessage, pszColMessage );
+ VGUIMessageBox( this, "Error Initializing Paths", pszMessage );
+ }
+}
+
+
+void CQCGenerator::DeleteLOD()
+{
+ int numSelected = m_pLODPanel->GetSelectedItemsCount();
+ int selected;
+ for ( int i = numSelected-1; i >= 0; i-- )
+ {
+ selected = m_pLODPanel->GetSelectedItem( i );
+ m_pLODPanel->RemoveItem( selected );
+ }
+}
+
+void CQCGenerator::EditLOD()
+{
+ int numSelected = m_pLODPanel->GetSelectedItemsCount();
+ if ( numSelected == 1 && !m_pLODPanel->IsInEditMode() )
+ {
+ if ( m_pLODEdit )
+ {
+ m_pLODEdit->MarkForDeletion();
+ m_pLODEdit = NULL;
+ }
+ m_pLODEdit = new vgui::TextEntry( this, "Edit" );
+ m_pLODEdit->SendNewLine( true );
+ m_nSelectedSequence = m_pLODPanel->GetSelectedItem( 0 );
+ m_nSelectedColumn = m_pLODPanel->GetSelectedColumn();
+ m_pLODPanel->EnterEditMode( m_nSelectedSequence, m_nSelectedColumn, m_pLODEdit );
+ }
+}
+
+void CQCGenerator::OnNewLODText()
+{
+ KeyValues *pEditItem = m_pLODPanel->GetItem( m_nSelectedSequence );
+ KeyValues *pListItem = pEditItem;
+ wchar_t szEditText[MAX_PATH];
+
+ pEditItem = pEditItem->GetFirstValue();
+ const char *name = pEditItem->GetName();
+ for( int i = 0; i < m_nSelectedColumn; i++ )
+ {
+ pEditItem = pEditItem->GetNextValue();
+ name = pEditItem->GetName();
+ }
+ m_pLODEdit->GetText( szEditText, MAX_PATH );
+
+ pListItem->SetWString( name, szEditText );
+
+ m_pLODPanel->LeaveEditMode();
+ m_pLODPanel->InvalidateLayout();
+ return;
+} \ No newline at end of file