//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose: 
//
//=============================================================================

#if defined(WIN32) && !defined( _GAMECONSOLE )
#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

// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"


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 );	
	Q_strcpy( pszCollisionPath, tempText );

	pTargetField = pQCGenerator->FindChildByName( "surfacePropertyDropDown" );
	((ComboBox *)pTargetField)->GetText( tempText, MAX_PATH );
    Q_strcpy( pszSurfaceProperty, tempText );

	pTargetField = pQCGenerator->FindChildByName( "materialsField" );
	((TextEntry *)pTargetField)->GetText( tempText, MAX_PATH );
	Q_strcpy( 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;

		Q_strcpy( 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, char *pszName, const char *pszDir, char *pszFilter, 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, '\\' );
		Q_strcpy( pszEndGamePath, "\\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 )
{
    Q_strcpy( 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 );
	strcpy( szName, szPath);
	strcat( szName, m_QCInfo_t.pszSceneName);
	strcat( 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 );
	strcat( 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) ? true : false;
#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 )
{
	strcpy( 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.
				strcpy( m_QCInfo_t.pszSMDPath, pszPath );
				strcat( m_QCInfo_t.pszSMDPath, filename );
			}
			if ( !strncmp( filenameEnd, "_phy", 4) || !strncmp( filenameEnd, "_col", 4 ) )
			{
				bFoundCollision = true;
				//we have found the collision smd.
				strcpy( m_QCInfo_t.pszCollisionPath, pszPath );
				strcat( 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 )
	{
		strcat( m_QCInfo_t.pszSMDPath, pszPath );
		strcat( m_QCInfo_t.pszSMDPath, pszScene );		
		strcat( 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 );
		strcpy( m_QCInfo_t.pszCollisionPath, m_QCInfo_t.pszSMDPath );
		m_QCInfo_t.bReferenceAsPhys = true;
	}
	if ( !bFoundReference || !bFoundCollision)
	{
		Q_strcpy( pszMessage, pszRefMessage );
		Q_strcat( pszMessage, pszColMessage, 1024 );
		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->DeletePanel();
			m_pLODEdit = 0;
		}
		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;
}