summaryrefslogtreecommitdiff
path: root/vgui2/dme_controls/AssetBuilder.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /vgui2/dme_controls/AssetBuilder.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'vgui2/dme_controls/AssetBuilder.cpp')
-rw-r--r--vgui2/dme_controls/AssetBuilder.cpp1725
1 files changed, 1725 insertions, 0 deletions
diff --git a/vgui2/dme_controls/AssetBuilder.cpp b/vgui2/dme_controls/AssetBuilder.cpp
new file mode 100644
index 0000000..cfb7c2a
--- /dev/null
+++ b/vgui2/dme_controls/AssetBuilder.cpp
@@ -0,0 +1,1725 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "dme_controls/AssetBuilder.h"
+#include "dme_controls/DmePanel.h"
+#include "dme_controls/dmecontrols_utils.h"
+#include "tier1/KeyValues.h"
+#include "vgui_controls/ListPanel.h"
+#include "vgui_controls/MenuButton.h"
+#include "vgui_controls/TextEntry.h"
+#include "vgui_controls/MessageBox.h"
+#include "vgui_controls/ComboBox.h"
+#include "vgui_controls/FileOpenDialog.h"
+#include "vgui_controls/Splitter.h"
+#include "vgui_controls/FileOpenStateMachine.h"
+#include "vgui_controls/PropertySheet.h"
+#include "vgui_controls/PropertyPage.h"
+#include "vgui/ischeme.h"
+#include "vgui/IVGui.h"
+#include "vgui/ISurface.h"
+#include "tier1/tier1.h"
+#include "movieobjects/dmemakefile.h"
+#include "matsys_controls/picker.h"
+#include "tier2/fileutils.h"
+#include "vgui/keycode.h"
+#include "filesystem.h"
+#include "movieobjects/idmemakefileutils.h"
+#include "tier3/tier3.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+using namespace vgui;
+
+#define ASSET_FILE_FORMAT "model"
+
+//-----------------------------------------------------------------------------
+// Compile status bar
+//-----------------------------------------------------------------------------
+class CCompileStatusBar : public vgui::EditablePanel
+{
+ DECLARE_CLASS_SIMPLE( CCompileStatusBar, EditablePanel );
+
+public:
+ enum CompileStatus_t
+ {
+ NOT_COMPILING,
+ CURRENTLY_COMPILING,
+ COMPILATION_FAILED,
+ COMPILATION_SUCCESSFUL
+ };
+
+ CCompileStatusBar( vgui::Panel *pParent, const char *pPanelName );
+ virtual ~CCompileStatusBar();
+
+ virtual void PaintBackground();
+
+ void SetStatus( CompileStatus_t status, const char *pMessage );
+
+private:
+ vgui::Label *m_pStatus;
+ CompileStatus_t m_Status;
+ int m_CompilingId;
+};
+
+
+//-----------------------------------------------------------------------------
+// Constructor, destructor
+//-----------------------------------------------------------------------------
+CCompileStatusBar::CCompileStatusBar( vgui::Panel *pParent, const char *pPanelName ) :
+ BaseClass( pParent, pPanelName )
+{
+ m_pStatus = new vgui::Label( this, "StatusLabel", "" );
+ m_pStatus->SetAutoResize( PIN_TOPLEFT, AUTORESIZE_DOWNANDRIGHT, 0, 0, 0, 0 );
+ m_pStatus->SetContentAlignment( vgui::Label::a_center );
+ m_pStatus->SetTextColorState( vgui::Label::CS_BRIGHT );
+ SetStatus( NOT_COMPILING, "" );
+ SetPaintBackgroundEnabled( true );
+ m_CompilingId = vgui::surface()->DrawGetTextureId( "vgui/progressbar" );
+ if ( m_CompilingId == -1 ) // we didn't find it, so create a new one
+ {
+ m_CompilingId = vgui::surface()->CreateNewTextureID();
+ vgui::surface()->DrawSetTextureFile( m_CompilingId, "vgui/progressbar", true, false );
+ }
+}
+
+CCompileStatusBar::~CCompileStatusBar()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets compile status
+//-----------------------------------------------------------------------------
+void CCompileStatusBar::SetStatus( CompileStatus_t status, const char *pMessage )
+{
+ m_Status = status;
+ m_pStatus->SetText( pMessage );
+}
+
+
+void CCompileStatusBar::PaintBackground()
+{
+ int w, h;
+ GetSize( w, h );
+
+ switch( m_Status )
+ {
+ case NOT_COMPILING:
+ break;
+
+ case COMPILATION_FAILED:
+ vgui::surface()->DrawSetColor( 255, 0, 0, 255 );
+ vgui::surface()->DrawFilledRect( 0, 0, w, h );
+ break;
+
+ case COMPILATION_SUCCESSFUL:
+ vgui::surface()->DrawSetColor( 0, 255, 0, 255 );
+ vgui::surface()->DrawFilledRect( 0, 0, w, h );
+ break;
+
+ case CURRENTLY_COMPILING:
+ {
+ float du = Plat_FloatTime() / 5.0f;
+ du -= (int)du;
+ du = 1.0f - du;
+
+ Vertex_t verts[4];
+ verts[0].Init( Vector2D( 0.0f, 0.0f ), Vector2D( du, 0.0f ) );
+ verts[1].Init( Vector2D( w, 0.0f ), Vector2D( 1.0f + du, 0.0f ) );
+ verts[2].Init( Vector2D( w, h ), Vector2D( 1.0f + du, 1.0f ) );
+ verts[3].Init( Vector2D( 0.0f, h ), Vector2D( du, 1.0f ) );
+
+ vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
+ vgui::surface()->DrawSetTexture( m_CompilingId );
+ vgui::surface()->DrawTexturedPolygon( 4, verts );
+ }
+ break;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Asset Builder
+//
+//-----------------------------------------------------------------------------
+IMPLEMENT_DMEPANEL_FACTORY( CAssetBuilder, DmeMakefile, "DmeMakeFileDefault", "MakeFile Editor", true );
+
+
+//-----------------------------------------------------------------------------
+// Static data
+//-----------------------------------------------------------------------------
+static PickerList_t s_AssetTypes;
+static bool s_bAssetTypeListBuilt = false;
+
+
+//-----------------------------------------------------------------------------
+// Builds the list of asset types
+//-----------------------------------------------------------------------------
+void BuildAssetTypeList( )
+{
+ if ( s_bAssetTypeListBuilt )
+ return;
+
+ s_bAssetTypeListBuilt = true;
+
+ CDisableUndoScopeGuard guard;
+
+ int hFactory = g_pDataModel->GetFirstFactory();
+ while ( g_pDataModel->IsValidFactory( hFactory ) )
+ {
+ // Add all DmeElements that inherit from DmeMakefile
+ const char *pFactoryName = g_pDataModel->GetFactoryName( hFactory );
+ CDmElement *pElement = GetElement< CDmElement >( g_pDataModel->CreateElement( pFactoryName, "temp" ) );
+ CDmeMakefile *pMakeFile = CastElement<CDmeMakefile>( pElement );
+ if ( pMakeFile && pMakeFile->GetMakefileType() )
+ {
+ int i = s_AssetTypes.AddToTail();
+ s_AssetTypes[i].m_pChoiceString = pMakeFile->GetMakefileType()->m_pHumanReadableName;
+ s_AssetTypes[i].m_pChoiceValue = pFactoryName;
+ }
+ DestroyElement( pElement );
+
+ hFactory = g_pDataModel->GetNextFactory( hFactory );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Builds the list of asset types
+//-----------------------------------------------------------------------------
+static PickerList_t &BuildAssetSubTypeList( const char **ppSubTypes, PickerList_t &pickerList )
+{
+ if ( !ppSubTypes )
+ return s_AssetTypes;
+
+ pickerList.RemoveAll();
+
+ CDisableUndoScopeGuard guard;
+
+ int nCount = s_AssetTypes.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ // Add all DmeElements that inherit from DmeMakefile
+ CDmElement *pElement = GetElement< CDmElement >( g_pDataModel->CreateElement( s_AssetTypes[i].m_pChoiceValue, "temp" ) );
+ CDmeMakefile *pMakeFile = CastElement< CDmeMakefile >( pElement );
+
+ for ( int j = 0; ppSubTypes[j]; ++j )
+ {
+ if ( !pElement->IsA( ppSubTypes[j] ) )
+ continue;
+
+ int k = pickerList.AddToTail();
+ pickerList[k].m_pChoiceString = pMakeFile->GetMakefileType()->m_pHumanReadableName;
+ pickerList[k].m_pChoiceValue = s_AssetTypes[i].m_pChoiceValue;
+ break;
+ }
+ DestroyElement( pElement );
+ }
+
+ return pickerList;
+}
+
+
+//-----------------------------------------------------------------------------
+// Shows the overwrite existing file dialog
+//-----------------------------------------------------------------------------
+static void OverwriteFileDialog( vgui::Panel *pActionTarget, const char *pFileName, KeyValues *pOkCommand )
+{
+ if ( !g_pFullFileSystem->FileExists( pFileName ) )
+ {
+ pActionTarget->PostMessage( pActionTarget->GetVPanel(), pOkCommand );
+ return;
+ }
+
+ char pBuf[1024];
+ Q_snprintf( pBuf, sizeof(pBuf), "File already exists. Overwrite it?\n\n\"%s\"\n", pFileName );
+ vgui::MessageBox *pMessageBox = new vgui::MessageBox( "Overwrite Existing File?", pBuf, pActionTarget );
+ pMessageBox->AddActionSignalTarget( pActionTarget );
+ pMessageBox->SetOKButtonVisible( true );
+ pMessageBox->SetOKButtonText( "Yes" );
+ pMessageBox->SetCancelButtonVisible( true );
+ pMessageBox->SetCancelButtonText( "No" );
+ pMessageBox->SetCloseButtonVisible( false );
+ pMessageBox->SetCommand( pOkCommand );
+ pMessageBox->DoModal();
+}
+
+
+//-----------------------------------------------------------------------------
+// Utility to load a makefile
+//-----------------------------------------------------------------------------
+static CDmeMakefile *ReadMakefile( const char *pFileName, CDmElement **ppRoot = NULL )
+{
+ if ( ppRoot )
+ {
+ *ppRoot = NULL;
+ }
+
+ CDmElement *pRoot;
+ DmFileId_t fileid = g_pDataModel->RestoreFromFile( pFileName, NULL, NULL, &pRoot, CR_DELETE_OLD );
+ if ( fileid == DMFILEID_INVALID || !pRoot )
+ {
+ Warning( "Unable to read makefile \"%s\"!\n", pFileName );
+ return NULL;
+ }
+
+ CDmeMakefile *pMakeFile = CastElement< CDmeMakefile >( pRoot );
+ if ( !pMakeFile )
+ {
+ CDmElement *pElement = CastElement< CDmElement >( pRoot );
+ pMakeFile = pElement->GetValueElement< CDmeMakefile >( "makefile" );
+ if ( !pMakeFile )
+ {
+ DmFileId_t fileId = pRoot->GetFileId();
+ DestroyElement( pRoot );
+ if ( fileId != DMFILEID_INVALID && g_pDataModel->GetFileName( fileId )[0] )
+ {
+ g_pDataModel->RemoveFileId( fileId );
+ }
+ return NULL;
+ }
+ }
+
+ if ( ppRoot )
+ {
+ *ppRoot = CastElement< CDmElement >( pRoot );
+ }
+ return pMakeFile;
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Sort by MDL name
+//-----------------------------------------------------------------------------
+static int __cdecl TypeSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
+{
+ const char *string1 = item1.kv->GetString("type");
+ const char *string2 = item2.kv->GetString("type");
+ int nRetVal = Q_stricmp( string1, string2 );
+ if ( nRetVal != 0 )
+ return nRetVal;
+
+ string1 = item1.kv->GetString("file");
+ string2 = item2.kv->GetString("file");
+ nRetVal = Q_stricmp( string1, string2 );
+ if ( nRetVal != 0 )
+ return nRetVal;
+
+ int nIndex1 = item1.kv->GetInt( "index" );
+ int nIndex2 = item2.kv->GetInt( "index" );
+ return nIndex1 - nIndex2;
+}
+
+static int __cdecl FileSortFunc( vgui::ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 )
+{
+ const char *string1 = item1.kv->GetString("file");
+ const char *string2 = item2.kv->GetString("file");
+ int nRetVal = Q_stricmp( string1, string2 );
+ if ( nRetVal != 0 )
+ return nRetVal;
+
+ string1 = item1.kv->GetString("type");
+ string2 = item2.kv->GetString("type");
+ nRetVal = Q_stricmp( string1, string2 );
+ if ( nRetVal != 0 )
+ return nRetVal;
+
+ int nIndex1 = item1.kv->GetInt( "index" );
+ int nIndex2 = item2.kv->GetInt( "index" );
+ return nIndex1 - nIndex2;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor, destructor
+//-----------------------------------------------------------------------------
+CAssetBuilder::CAssetBuilder( vgui::Panel *pParent, const char *pPanelName ) :
+ BaseClass( pParent, pPanelName )
+{
+ m_hContextMenu = NULL;
+ m_hRootMakefile = NULL;
+ m_bIsCompiling = false;
+ m_bDestroyMakefileOnClose = true;
+
+ m_pInputOutputSheet = new vgui::PropertySheet( this, "InputOutputSheet" );
+ m_pInputOutputSheet->AddActionSignalTarget( this );
+
+ m_pInputPage = new PropertyPage( m_pInputOutputSheet, "InputPage" );
+ m_pOutputPage = new PropertyPage( m_pInputOutputSheet, "OutputPage" );
+ m_pCompilePage = new PropertyPage( m_pInputOutputSheet, "CompilePage" );
+ m_pOutputPreviewPage = new PropertyPage( m_pInputOutputSheet, "OutputPreviewPage" );
+
+ m_pPropertiesSplitter = new vgui::Splitter( m_pInputPage, "PropertiesSplitter", SPLITTER_MODE_VERTICAL, 1 );
+
+ vgui::Panel *pSplitterLeftSide = m_pPropertiesSplitter->GetChild( 0 );
+ vgui::Panel *pSplitterRightSide = m_pPropertiesSplitter->GetChild( 1 );
+ m_pDmePanel = new CDmePanel( pSplitterRightSide, "CompileOptions" );
+ m_pDmePanel->AddActionSignalTarget( this );
+
+ m_pOututPreviewPanel = new CDmePanel( m_pOutputPreviewPage, "OutputPreview", false );
+ m_pOututPreviewPanel->AddActionSignalTarget( this );
+
+ m_pSourcesList = new vgui::ListPanel( pSplitterLeftSide, "SourcesList" );
+ m_pSourcesList->AddColumnHeader( 0, "type", "type", 100, 0 );
+ m_pSourcesList->AddColumnHeader( 1, "file", "file", 52, 0 );
+ m_pSourcesList->AddActionSignalTarget( this );
+ m_pSourcesList->SetSortFunc( 0, TypeSortFunc );
+ m_pSourcesList->SetSortFunc( 1, FileSortFunc );
+ m_pSourcesList->SetSortColumn( 0 );
+// m_pSourcesList->SetSelectIndividualCells( true );
+ m_pSourcesList->SetEmptyListText("No sources");
+// m_pSourcesList->SetDragEnabled( true );
+
+ m_pOutputList = new vgui::ListPanel( m_pOutputPage, "OutputList" );
+ m_pOutputList->AddColumnHeader( 0, "type", "type", 100, 0 );
+ m_pOutputList->AddColumnHeader( 1, "file", "file", 52, 0 );
+ m_pOutputList->AddActionSignalTarget( this );
+ m_pOutputList->SetSortFunc( 0, TypeSortFunc );
+ m_pOutputList->SetSortFunc( 1, FileSortFunc );
+ m_pOutputList->SetSortColumn( 0 );
+ m_pOutputList->SetEmptyListText("No outputs");
+
+ m_pCompileOutput = new vgui::TextEntry( m_pCompilePage, "CompileOutput" );
+ m_pCompileOutput->SetMultiline( true );
+ m_pCompileOutput->SetVerticalScrollbar( true );
+ m_pCompile = new vgui::Button( this, "CompileButton", "Compile", this, "OnCompile" );
+ m_pPublish = new vgui::Button( this, "PublishButton", "Publish", this, "OnPublish" );
+ m_pAbortCompile = new vgui::Button( this, "AbortCompileButton", "AbortCompile", this, "OnAbortCompile" );
+ m_pCompileStatusBar = new CCompileStatusBar( this, "CompileStatus" );
+
+ m_pInputPage->LoadControlSettingsAndUserConfig( "resource/assetbuilderinputpage.res" );
+ m_pOutputPage->LoadControlSettingsAndUserConfig( "resource/assetbuilderoutputpage.res" );
+ m_pCompilePage->LoadControlSettingsAndUserConfig( "resource/assetbuildercompilepage.res" );
+ m_pOutputPreviewPage->LoadControlSettingsAndUserConfig( "resource/assetbuilderoutputpreviewpage.res" );
+
+ // Load layout settings; has to happen before pinning occurs in code
+ LoadControlSettingsAndUserConfig( "resource/assetbuilder.res" );
+
+ // NOTE: Page adding happens *after* LoadControlSettingsAndUserConfig
+ // because the layout of the sheet is correct at this point.
+ m_pInputOutputSheet->AddPage( m_pInputPage, "Input" );
+ m_pInputOutputSheet->AddPage( m_pOutputPage, "Output" );
+ m_pInputOutputSheet->AddPage( m_pCompilePage, "Compile" );
+ m_pInputOutputSheet->AddPage( m_pOutputPreviewPage, "Preview" );
+
+ m_pCompile->SetEnabled( false );
+ m_pPublish->SetEnabled( false );
+ m_pAbortCompile->SetEnabled( false );
+}
+
+CAssetBuilder::~CAssetBuilder()
+{
+ if ( m_bDestroyMakefileOnClose )
+ {
+ CleanupMakefile();
+ }
+ CleanupContextMenu();
+ SaveUserConfig();
+}
+
+
+//-----------------------------------------------------------------------------
+// Default behavior is to destroy the makefile when we close
+//-----------------------------------------------------------------------------
+void CAssetBuilder::DestroyMakefileOnClose( bool bEnable )
+{
+ m_bDestroyMakefileOnClose = bEnable;
+}
+
+
+//-----------------------------------------------------------------------------
+// Builds a unique list of file IDs
+//-----------------------------------------------------------------------------
+void CAssetBuilder::BuildFileIDList( CDmeMakefile *pMakeFile, CUtlVector<DmFileId_t> &fileIds )
+{
+ if ( !pMakeFile )
+ return;
+
+ // NOTE: Not hugely efficient. If the CDmeDependencyMakefile starts
+ // getting large, we can optimize this
+ DmFileId_t id = pMakeFile->GetFileId();
+ int nCount = fileIds.Count();
+ int i;
+ for ( i = 0; i < nCount; ++i )
+ {
+ if ( fileIds[i] == id )
+ break;
+ }
+
+ if ( i == nCount )
+ {
+ fileIds.AddToTail( id );
+ }
+
+ int nSourceCount = pMakeFile->GetSourceCount();
+ for ( int i = 0; i < nSourceCount; ++i )
+ {
+ CDmeSource *pSource = pMakeFile->GetSource(i);
+ BuildFileIDList( pSource->GetDependentMakefile(), fileIds );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Removes a makefile from memory
+//-----------------------------------------------------------------------------
+void CAssetBuilder::CleanupMakefile()
+{
+ m_hMakefileStack.Clear();
+ m_pDmePanel->SetDmeElement( NULL );
+ m_pOututPreviewPanel->SetDmeElement( NULL );
+
+ if ( !m_hRootMakefile.Get() )
+ return;
+
+ // First, build a list of unique file IDs
+ CUtlVector<DmFileId_t> fileIds;
+ BuildFileIDList( m_hRootMakefile, fileIds );
+
+ CDisableUndoScopeGuard guard;
+
+ m_hRootMakefile = NULL;
+
+ int nCount = fileIds.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ if ( fileIds[i] != DMFILEID_INVALID && g_pDataModel->GetFileName( fileIds[i] )[0] )
+ {
+ g_pDataModel->RemoveFileId( fileIds[i] );
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Marks the file as dirty (or not)
+//-----------------------------------------------------------------------------
+void CAssetBuilder::SetDirty()
+{
+ PostActionSignal( new KeyValues( "DmeElementChanged" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the current makefile
+//-----------------------------------------------------------------------------
+CDmeMakefile *CAssetBuilder::GetMakeFile()
+{
+ return m_hMakefile.Get();
+}
+
+CDmeMakefile *CAssetBuilder::GetRootMakeFile()
+{
+ return m_hRootMakefile.Get();
+}
+
+
+//-----------------------------------------------------------------------------
+// Resets the lists; called when file name changes
+//-----------------------------------------------------------------------------
+void CAssetBuilder::Refresh()
+{
+ RefreshSourceList();
+ RefreshOutputList();
+}
+
+
+//-----------------------------------------------------------------------------
+// Resets the root makefile
+//-----------------------------------------------------------------------------
+void CAssetBuilder::SetRootMakefile( CDmeMakefile *pMakeFile )
+{
+ CleanupMakefile();
+
+ if ( pMakeFile )
+ {
+ m_hRootMakefile = pMakeFile;
+ m_hMakefileStack.Push( m_hRootMakefile );
+ }
+ SetCurrentMakefile( pMakeFile );
+}
+
+
+//-----------------------------------------------------------------------------
+// Resets the current makefile
+//-----------------------------------------------------------------------------
+void CAssetBuilder::SetCurrentMakefile( CDmeMakefile *pMakeFile )
+{
+ m_hMakefile = pMakeFile;
+ m_pDmePanel->SetDmeElement( NULL );
+ m_pOututPreviewPanel->SetDmeElement( pMakeFile, true, "DmeMakeFileOutputPreview" );
+ RefreshSourceList();
+ RefreshOutputList();
+
+ // Lets the asset builder update the title bar
+ PostActionSignal( new KeyValues( "UpdateFileName" ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Hook into the DME panel framework
+//-----------------------------------------------------------------------------
+void CAssetBuilder::SetDmeElement( CDmeMakefile *pMakeFile )
+{
+ SetRootMakefile( pMakeFile );
+}
+
+
+//-----------------------------------------------------------------------------
+// Refresh the source list
+//-----------------------------------------------------------------------------
+void CAssetBuilder::RefreshSourceList( )
+{
+ m_pSourcesList->RemoveAll();
+ if ( !m_hMakefile.Get() )
+ return;
+
+ DmeMakefileType_t *pSourceTypes = m_hMakefile->GetSourceTypes();
+ for ( int i = 0; pSourceTypes[i].m_pTypeName; ++i )
+ {
+ CUtlVector< CDmeHandle< CDmeSource > > sources;
+ m_hMakefile->GetSources( pSourceTypes[i].m_pTypeName, sources );
+ int nCount = sources.Count();
+ for ( int j = 0; j < nCount; ++j )
+ {
+ char pFullPath[MAX_PATH];
+ m_hMakefile->GetSourceFullPath( sources[j], pFullPath, sizeof(pFullPath) );
+
+ KeyValues *pItemKeys = new KeyValues( "node", "type", pSourceTypes[i].m_pHumanReadableName );
+ pItemKeys->SetString( "file", pFullPath );
+ pItemKeys->SetInt( "sourceTypeIndex", i );
+ pItemKeys->SetInt( "index", j ); // for sorting in the listpanel
+ SetElementKeyValue( pItemKeys, "dmeSource", sources[j] );
+ m_pSourcesList->AddItem( pItemKeys, 0, false, false );
+ }
+ }
+
+ m_pSourcesList->SortList();
+}
+
+
+//-----------------------------------------------------------------------------
+// Refreshes the output list
+//-----------------------------------------------------------------------------
+void CAssetBuilder::RefreshOutputList()
+{
+ m_pOutputList->RemoveAll();
+ m_pCompile->SetEnabled( false );
+ m_pPublish->SetEnabled( false );
+ if ( !m_hMakefile.Get() )
+ return;
+
+ CUtlVector<CUtlString> outputs;
+ m_hMakefile->GetOutputs( outputs );
+ int nCount = outputs.Count();
+ for ( int j = 0; j < nCount; ++j )
+ {
+ KeyValues *pItemKeys = new KeyValues( "node", "type", "Output" );
+ pItemKeys->SetString( "file", outputs[j] );
+ pItemKeys->SetInt( "index", j );
+ m_pOutputList->AddItem( pItemKeys, 0, false, false );
+ }
+
+ bool bEnabled = ( nCount > 0 ) && ( g_pDmeMakefileUtils != NULL );
+ m_pCompile->SetEnabled( bEnabled );
+ m_pPublish->SetEnabled( bEnabled );
+
+ m_pOutputList->SortList();
+}
+
+
+//-----------------------------------------------------------------------------
+// Selects a particular source
+//-----------------------------------------------------------------------------
+void CAssetBuilder::SelectSource( CDmeSource *pSource )
+{
+ int nItemID = m_pSourcesList->FirstItem();
+ for ( ; nItemID != m_pSourcesList->InvalidItemID(); nItemID = m_pSourcesList->NextItem( nItemID ) )
+ {
+ KeyValues *kv = m_pSourcesList->GetItem( nItemID );
+ if ( GetElementKeyValue< CDmeSource >( kv, "dmeSource" ) != pSource )
+ continue;
+
+ m_pSourcesList->SetSingleSelectedItem( nItemID );
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by the picker popped up in OnFileNew
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnPicked( KeyValues *kv )
+{
+ const char *pValue = kv->GetString( "choice" );
+
+ KeyValues *pContextKeys = kv->FindKey( "OnAddSource" );
+ if ( pContextKeys )
+ {
+ OnSourceFileAdded( "", pValue );
+ return;
+ }
+
+ CDisableUndoScopeGuard guard;
+ CDmeMakefile *pMakeFile = GetElement< CDmeMakefile >( g_pDataModel->CreateElement( pValue, "unnamed" ) );
+ if ( !pMakeFile )
+ return;
+
+ DmeMakefileType_t *pType = pMakeFile->GetMakefileType();
+
+ char pContext[MAX_PATH];
+ Q_snprintf( pContext, sizeof(pContext), "asset_builder_session_%s", pType->m_pTypeName );
+
+ char pStartingDir[MAX_PATH];
+ pMakeFile->GetDefaultDirectory( pType->m_pDefaultDirectoryID, pStartingDir, sizeof(pStartingDir) );
+ g_pFullFileSystem->CreateDirHierarchy( pStartingDir );
+
+ KeyValues *pDialogKeys = new KeyValues( "NewSourceFileSelected", "makefileType", pValue );
+ FileOpenDialog *pDialog = new FileOpenDialog( this, "Select Asset Builder File Name", false, pDialogKeys );
+ pDialog->SetStartDirectoryContext( pContext, pStartingDir );
+ pDialog->AddFilter( pType->m_pFileFilter, pType->m_pFileFilterString, true );
+ pDialog->SetDeleteSelfOnClose( true );
+ pDialog->AddActionSignalTarget( this );
+ pDialog->DoModal( false );
+ DestroyElement( pMakeFile );
+}
+
+
+//-----------------------------------------------------------------------------
+// Creates a new source file, hooks it in
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnNewSourceFile( )
+{
+ KeyValues *pKeyValues = GetSelectedSourceKeyvalues();
+ CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
+ if ( !pSource )
+ return;
+
+ BuildAssetTypeList();
+
+ PickerList_t typePickerList;
+ PickerList_t &pickerList = BuildAssetSubTypeList( pSource->GetSourceMakefileTypes(), typePickerList );
+
+ // Create a list indicating which type of asset to create
+ CPickerFrame *pPicker = new CPickerFrame( this, "Select Sub-Asset Type", "Asset Type", "assetType" );
+ pPicker->DoModal( pickerList );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the button to add a file is clicked
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnAddSource( )
+{
+ if ( !m_hMakefile.Get() )
+ return;
+
+ PickerList_t sourceType;
+
+ DmeMakefileType_t *pSourceTypes = m_hMakefile->GetSourceTypes();
+ for ( int i = 0; pSourceTypes[i].m_pTypeName; ++i )
+ {
+ if ( pSourceTypes[i].m_bIsSingleton )
+ {
+ if ( m_hMakefile->HasSourceOfType( pSourceTypes[i].m_pTypeName ) )
+ continue;
+ }
+
+ int j = sourceType.AddToTail( );
+ sourceType[j].m_pChoiceString = pSourceTypes[i].m_pHumanReadableName;
+ sourceType[j].m_pChoiceValue = pSourceTypes[i].m_pTypeName;
+ }
+
+ if ( sourceType.Count() == 0 )
+ return;
+
+ KeyValues *pContextKeys = new KeyValues( "OnAddSource" );
+ CPickerFrame *pPicker = new CPickerFrame( this, "Select Source Type", "Source Type", "sourceType" );
+ pPicker->DoModal( sourceType, pContextKeys );
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the curerntly selected row
+//-----------------------------------------------------------------------------
+int CAssetBuilder::GetSelectedRow( )
+{
+ int nItemID = m_pSourcesList->GetSelectedItem( 0 );
+ return ( nItemID != -1 ) ? m_pSourcesList->GetItemCurrentRow( nItemID ) : -1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Selects a particular row of the source list
+//-----------------------------------------------------------------------------
+void CAssetBuilder::SelectSourceListRow( int nRow )
+{
+ int nVisibleRowCount = m_pSourcesList->GetItemCount();
+ if ( nVisibleRowCount == 0 || nRow < 0 )
+ return;
+
+ if ( nRow >= nVisibleRowCount )
+ {
+ nRow = nVisibleRowCount - 1;
+ }
+
+ int nNewItemID = m_pSourcesList->GetItemIDFromRow( nRow );
+ m_pSourcesList->SetSingleSelectedItem( nNewItemID );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the button to remove a file is clicked
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnRemoveSource( )
+{
+ int nCount = m_pSourcesList->GetSelectedItemsCount();
+ if ( nCount == 0 || !m_hMakefile.Get() )
+ return;
+
+ int nRow = GetSelectedRow();
+ Assert( nRow >= 0 );
+
+ // Update the selection to be reasonable after deletion
+ CDisableUndoScopeGuard guard;
+ for ( int i = 0; i < nCount; ++i )
+ {
+ int nItemID = m_pSourcesList->GetSelectedItem( i );
+ KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
+ CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
+ if ( pSource )
+ {
+ m_hMakefile->RemoveSource( pSource );
+ DestroyElement( pSource );
+ SetDirty( );
+ }
+ }
+
+ RefreshSourceList();
+
+ SelectSourceListRow( nRow );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to make a particular source the currently selected source
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnZoomInSource()
+{
+ // Called to zoom into the currently selected source
+ CDmeSource *pSource = GetSelectedSource( );
+ if ( !pSource )
+ return;
+
+ CDmeMakefile *pChild = m_hMakefile->FindDependentMakefile( pSource );
+ if ( pChild )
+ {
+ CDmeHandle< CDmeMakefile > hChild;
+ hChild = pChild;
+ m_hMakefileStack.Push( hChild );
+ SetCurrentMakefile( pChild );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to zoom out of a particular source
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnZoomOutSource()
+{
+ // Called to zoom into the currently selected source
+ if ( m_hMakefileStack.Count() <= 1 )
+ return;
+
+ CDmeMakefile *pOldParent = m_hMakefileStack.Top().Get();
+ m_hMakefileStack.Pop( );
+ CDmeMakefile *pParent = m_hMakefileStack.Top().Get();
+ if ( pParent )
+ {
+ SetCurrentMakefile( pParent );
+ CDmeSource *pSource = pParent->FindAssociatedSource( pOldParent );
+ if ( pSource )
+ {
+ SelectSource( pSource );
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a key is typed
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnKeyCodeTyped( vgui::KeyCode code )
+{
+ if ( code == KEY_DELETE )
+ {
+ OnRemoveSource();
+ return;
+ }
+
+ if ( code == KEY_ENTER )
+ {
+ OnZoomInSource();
+ return;
+ }
+
+ BaseClass::OnKeyCodeTyped( code );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when we're browsing for a source file and one was selected
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnSourceFileAdded( const char *pFileName, const char *pTypeName )
+{
+ CDmeSource *pSource = NULL;
+ {
+ CDisableUndoScopeGuard guard;
+ pSource = m_hMakefile->AddSource( pTypeName, pFileName );
+ }
+ SetDirty( );
+ RefreshSourceList( );
+ SelectSource( pSource );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the file open dialog for browsing source files selects something
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnNewSourceFileSelected( const char *pFileName, KeyValues *kv )
+{
+ int nCount = m_pSourcesList->GetSelectedItemsCount();
+ if ( nCount != 1 || !m_hMakefile.Get() )
+ return;
+
+ int nItemID = m_pSourcesList->GetSelectedItem( 0 );
+ KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
+ CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
+ if ( !pSource )
+ return;
+
+ const char *pMakeFileType = kv->GetString( "makefileType" );
+
+ {
+ CDisableUndoScopeGuard guard;
+ m_hMakefile->SetSourceFullPath( pSource, pFileName );
+
+ DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( pFileName );
+ CDmeMakefile *pSourceMakeFile = CreateElement< CDmeMakefile >( pMakeFileType, pFileName, fileid );
+ pSourceMakeFile->SetFileName( pFileName );
+
+ m_hMakefile->SetAssociation( pSource, pSourceMakeFile );
+ SetDirty( );
+ }
+
+ pKeyValues->SetString( "file", pFileName );
+ m_pSourcesList->ApplyItemChanges( nItemID );
+ m_pSourcesList->SortList();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the file open dialog for browsing source files selects something
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnFileSelected( KeyValues *kv )
+{
+ const char *pFileName = kv->GetString( "fullpath", NULL );
+ if ( !pFileName )
+ return;
+
+ KeyValues *pDialogKeys = kv->FindKey( "SelectSourceFile" );
+ if ( pDialogKeys )
+ {
+ OnSourceFileNameChanged( pFileName );
+ return;
+ }
+
+ pDialogKeys = kv->FindKey( "NewSourceFileSelected" );
+ if ( pDialogKeys )
+ {
+ if ( !g_pFullFileSystem->FileExists( pFileName ) )
+ {
+ OnNewSourceFileSelected( pFileName, pDialogKeys );
+ }
+ else
+ {
+ OnSourceFileNameChanged( pFileName );
+ }
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Shows the source file browser
+//-----------------------------------------------------------------------------
+void CAssetBuilder::ShowSourceFileBrowser( const char *pTitle, DmeMakefileType_t *pSourceType, KeyValues *pDialogKeys )
+{
+ char pContext[MAX_PATH];
+ Q_snprintf( pContext, sizeof(pContext), "asset_builder_session_%s", pSourceType->m_pTypeName );
+
+ char pStartingDir[MAX_PATH];
+ m_hMakefile->GetDefaultDirectory( pSourceType->m_pDefaultDirectoryID, pStartingDir, sizeof(pStartingDir) );
+ g_pFullFileSystem->CreateDirHierarchy( pStartingDir );
+
+ FileOpenDialog *pDialog = new FileOpenDialog( this, pTitle, true, pDialogKeys );
+ pDialog->SetStartDirectoryContext( pContext, pStartingDir );
+ pDialog->AddFilter( pSourceType->m_pFileFilter, pSourceType->m_pFileFilterString, true );
+ pDialog->SetDeleteSelfOnClose( true );
+ pDialog->AddActionSignalTarget( this );
+ pDialog->DoModal( false );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the button to browse for a source file is clicked
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnBrowseSourceFile( )
+{
+ KeyValues *pKeyValues = GetSelectedSourceKeyvalues();
+ if ( !pKeyValues )
+ return;
+
+ int nSourceTypeIndex = pKeyValues->GetInt( "sourceTypeIndex", -1 );
+
+ KeyValues *pDialogKeys = new KeyValues( "SelectSourceFile" );
+ DmeMakefileType_t &sourceType = m_hMakefile->GetSourceTypes()[nSourceTypeIndex];
+ ShowSourceFileBrowser( "Select Source File", &sourceType, pDialogKeys );
+}
+
+
+//-----------------------------------------------------------------------------
+// Command handler
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnCommand( const char *pCommand )
+{
+ if ( !Q_stricmp( pCommand, "OnCompile" ) )
+ {
+ OnCompile();
+ return;
+ }
+
+ if ( !Q_stricmp( pCommand, "OnAbortCompile" ) )
+ {
+ OnAbortCompile();
+ return;
+ }
+
+ if ( !Q_stricmp( pCommand, "OnPublish" ) )
+ {
+ OnPublish();
+ return;
+ }
+
+ BaseClass::OnCommand( pCommand );
+}
+
+
+//-----------------------------------------------------------------------------
+// Cleans up the context menu
+//-----------------------------------------------------------------------------
+void CAssetBuilder::CleanupContextMenu()
+{
+ if ( m_hContextMenu.Get() )
+ {
+ m_hContextMenu->MarkForDeletion();
+ m_hContextMenu = NULL;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open a context-sensitive menu for a particular menu item
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnOpenContextMenu( KeyValues *kv )
+{
+ CleanupContextMenu();
+ if ( !m_hMakefile.Get() )
+ return;
+
+ Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
+ int nItemID = kv->GetInt( "itemID", -1 );
+
+ if ( pPanel != m_pSourcesList )
+ return;
+
+ m_hContextMenu = new Menu( this, "ActionMenu" );
+ m_hContextMenu->AddMenuItem( "Add...", new KeyValues( "AddSource" ), this );
+ int nCount = m_pSourcesList->GetSelectedItemsCount();
+ if ( nCount > 0 )
+ {
+ m_hContextMenu->AddMenuItem( "Remove", new KeyValues( "RemoveSource" ), this );
+ }
+
+ bool bShowZoomIn = false;
+ bool bShowZoomOut = m_hMakefileStack.Count() > 1;
+ bool bShowLoadSourceFile = false;
+ bool bHasValidSourceFile = false;
+ if ( nCount == 1 && nItemID != -1 )
+ {
+ KeyValues *kv = m_pSourcesList->GetItem( nItemID );
+ CDmeSource *pSource = GetElementKeyValue< CDmeSource >( kv, "dmeSource" );
+ if ( pSource )
+ {
+ bHasValidSourceFile = pSource->GetRelativeFileName()[0] != 0;
+ if ( m_hMakefile->FindDependentMakefile( pSource ) )
+ {
+ bShowZoomIn = true;
+ }
+ else
+ {
+ bShowLoadSourceFile = bHasValidSourceFile;
+ }
+ }
+ }
+
+ if ( bShowZoomIn || bShowZoomOut )
+ {
+ m_hContextMenu->AddSeparator();
+ if ( bShowZoomIn )
+ {
+ m_hContextMenu->AddMenuItem( "Zoom In", new KeyValues( "ZoomInSource" ), this );
+ }
+ if ( bShowZoomOut )
+ {
+ m_hContextMenu->AddMenuItem( "Zoom Out", new KeyValues( "ZoomOutSource" ), this );
+ }
+ }
+
+ if ( nCount == 1 )
+ {
+ m_hContextMenu->AddSeparator();
+ m_hContextMenu->AddMenuItem( "New Source File...", new KeyValues( "NewSourceFile" ), this );
+ m_hContextMenu->AddMenuItem( "Select Source File...", new KeyValues( "BrowseSourceFile" ), this );
+ if ( bShowLoadSourceFile )
+ {
+ m_hContextMenu->AddMenuItem( "Load Source File", new KeyValues( "LoadSourceFile" ), this );
+ }
+ if ( bHasValidSourceFile )
+ {
+ m_hContextMenu->AddMenuItem( "Edit Source File", new KeyValues( "EditSourceFile" ), this );
+ }
+ }
+
+ Menu::PlaceContextMenu( this, m_hContextMenu.Get() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnSourceItemSelectionChanged( )
+{
+ int nCount = m_pSourcesList->GetSelectedItemsCount();
+ if ( nCount != 1 )
+ {
+ m_pDmePanel->SetDmeElement( NULL );
+ return;
+ }
+
+ int nItemID = m_pSourcesList->GetSelectedItem( 0 );
+ KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
+ CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
+ m_pDmePanel->SetDmeElement( pSource );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnItemSelected( KeyValues *kv )
+{
+ Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
+ if ( pPanel == m_pSourcesList )
+ {
+ OnSourceItemSelectionChanged();
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when a list panel's selection changes
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnItemDeselected( KeyValues *kv )
+{
+ Panel *pPanel = (Panel *)kv->GetPtr( "panel", NULL );
+ if ( pPanel == m_pSourcesList )
+ {
+ OnSourceItemSelectionChanged();
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the selected source (if there's only 1 source selected)
+//-----------------------------------------------------------------------------
+CDmeSource *CAssetBuilder::GetSelectedSource( )
+{
+ int nCount = m_pSourcesList->GetSelectedItemsCount();
+ if ( nCount != 1 || !m_hMakefile.Get() )
+ return NULL;
+
+ int nItemID = m_pSourcesList->GetSelectedItem( 0 );
+ KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
+ return GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
+}
+
+KeyValues *CAssetBuilder::GetSelectedSourceKeyvalues( )
+{
+ int nCount = m_pSourcesList->GetSelectedItemsCount();
+ if ( nCount != 1 || !m_hMakefile.Get() )
+ return NULL;
+
+ int nItemID = m_pSourcesList->GetSelectedItem( 0 );
+ return m_pSourcesList->GetItem( nItemID );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the source file name changes
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnSourceFileNameChanged( const char *pFileName )
+{
+ int nCount = m_pSourcesList->GetSelectedItemsCount();
+ if ( nCount != 1 || !m_hMakefile.Get() )
+ return;
+
+ int nItemID = m_pSourcesList->GetSelectedItem( 0 );
+ KeyValues *pKeyValues = m_pSourcesList->GetItem( nItemID );
+ CDmeSource *pSource = GetElementKeyValue< CDmeSource >( pKeyValues, "dmeSource" );
+ if ( !pSource )
+ return;
+
+ {
+ CDisableUndoScopeGuard guard;
+ m_hMakefile->SetSourceFullPath( pSource, pFileName );
+ SetDirty( );
+ }
+
+ pKeyValues->SetString( "file", pFileName );
+ m_pSourcesList->ApplyItemChanges( nItemID );
+ m_pSourcesList->SortList();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called during compilation
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnLoadSourceFile()
+{
+ CDmeSource *pSource = GetSelectedSource( );
+ if ( !pSource )
+ return;
+
+ char pFullPath[MAX_PATH];
+ m_hMakefile->GetSourceFullPath( pSource, pFullPath, sizeof(pFullPath) );
+
+ {
+ CDisableUndoScopeGuard guard;
+
+ CDmElement *pRoot;
+ CDmeMakefile *pMakeFile = ReadMakefile( pFullPath, &pRoot );
+ if ( !pMakeFile )
+ return;
+
+ // Successfully loaded a makefile. Set up the association.
+ m_hMakefile->SetAssociation( pSource, pMakeFile );
+
+ // Refresh the dme panel... setting association could provoke changes
+ m_pDmePanel->SetDmeElement( pSource, true );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called to open an external editor for this source file
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnEditSourceFile()
+{
+ CDmeSource *pSource = GetSelectedSource( );
+ if ( pSource )
+ {
+ pSource->OpenEditor();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Finishes compilation
+//-----------------------------------------------------------------------------
+void CAssetBuilder::FinishCompilation( CompilationState_t state )
+{
+ // NOTE: compilation can cause the makefile to be completely
+ // rebuilt if it's sitting in the output file. Therefore,
+ // Detach the source preview panel from the source and refresh the
+ // source list to get it to correctly reconnect to the new source elements
+ m_pDmePanel->SetDmeElement( NULL );
+ int nRow = GetSelectedRow();
+
+ m_pOututPreviewPanel->SetDmeElement( m_hMakefile, true, "DmeMakeFileOutputPreview" );
+ m_bIsCompiling = false;
+
+ // NOTE: Sort of side-effecty. These two things must be done after
+ // m_pOututPreviewPanel->SetDmeElement, since that's what reloads the output element,
+ // which is also what can cause a reload of the makefile
+ RefreshSourceList();
+ SelectSourceListRow( nRow );
+
+ // Lets the asset builder update the title bar
+ // (compilation could have changed the dirty state if the makefile is in the file)
+ PostActionSignal( new KeyValues( "UpdateFileName" ) );
+
+ if ( state == COMPILATION_FAILED )
+ {
+ char pBuf[256];
+ Q_snprintf( pBuf, sizeof(pBuf), "Compilation Error (return code %d)", g_pDmeMakefileUtils->GetExitCode() );
+ m_pCompileStatusBar->SetStatus( CCompileStatusBar::COMPILATION_FAILED, pBuf );
+ }
+ else
+ {
+ m_pCompileStatusBar->SetStatus( CCompileStatusBar::COMPILATION_SUCCESSFUL, "Compile Successful!" );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called during compilation
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnTick()
+{
+ BaseClass::OnTick();
+
+ if ( m_bIsCompiling )
+ {
+ int nLen = g_pDmeMakefileUtils->GetCompileOutputSize( );
+ char *pBuf = (char*)_alloca( nLen+1 );
+ CompilationState_t state = g_pDmeMakefileUtils->UpdateCompilation( pBuf, nLen );
+ if ( nLen > 0 )
+ {
+ m_pCompileOutput->InsertString( pBuf );
+ }
+ Assert( m_hMakefile.Get() );
+ if ( state != COMPILATION_NOT_COMPLETE )
+ {
+ FinishCompilation( state );
+ }
+ }
+
+ if ( !m_bIsCompiling )
+ {
+ m_pAbortCompile->SetEnabled( false );
+ vgui::ivgui()->RemoveTickSignal( GetVPanel() );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Abort compile asset
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnAbortCompile()
+{
+ if ( m_bIsCompiling )
+ {
+ g_pDmeMakefileUtils->AbortCurrentCompilation();
+ m_bIsCompiling = false;
+ m_pAbortCompile->SetEnabled( false );
+ m_pCompileStatusBar->SetStatus( CCompileStatusBar::COMPILATION_FAILED, "Compile Aborted" );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Compile asset
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnCompile( )
+{
+ if ( !m_hMakefile.Get() )
+ return;
+
+ OnAbortCompile();
+
+ m_pCompileOutput->SetText( "" );
+ g_pDmeMakefileUtils->PerformCompile( m_hMakefile, false );
+ m_bIsCompiling = true;
+ m_pAbortCompile->SetEnabled( true );
+ m_pCompileStatusBar->SetStatus( CCompileStatusBar::CURRENTLY_COMPILING, "Compiling..." );
+
+ vgui::ivgui()->AddTickSignal( GetVPanel(), 10 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Compile, then publish
+//-----------------------------------------------------------------------------
+void CAssetBuilder::OnPublish( )
+{
+ if ( !m_hMakefile.Get() )
+ return;
+
+ OnAbortCompile();
+
+ m_pCompileOutput->SetText( "" );
+ g_pDmeMakefileUtils->PerformCompile( m_hMakefile, false );
+ m_bIsCompiling = true;
+ m_pAbortCompile->SetEnabled( true );
+ m_pCompileStatusBar->SetStatus( CCompileStatusBar::CURRENTLY_COMPILING, "Compiling..." );
+ vgui::ivgui()->AddTickSignal( GetVPanel(), 10 );
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor, destructor
+//-----------------------------------------------------------------------------
+CAssetBuilderFrame::CAssetBuilderFrame( vgui::Panel *pParent, const char *pTitle ) :
+ BaseClass( pParent, "AssetBuilderFrame" )
+{
+ m_TitleString = pTitle;
+
+ SetMenuButtonVisible( true );
+ SetImages( "resource/downarrow" );
+
+ m_pAssetBuilder = new CAssetBuilder( this, "AssetBuilder" );
+ m_pAssetBuilder->AddActionSignalTarget( this );
+
+ vgui::Menu *pMenu = new vgui::Menu( NULL, "FileMenu" );
+ pMenu->AddMenuItem( "new", "#AssetBuilder_FileNew", new KeyValues( "FileNew" ), this );
+ pMenu->AddMenuItem( "open", "#AssetBuilder_FileOpen", new KeyValues( "FileOpen" ), this );
+ pMenu->AddMenuItem( "save", "#AssetBuilder_FileSave", new KeyValues( "FileSave" ), this );
+ pMenu->AddMenuItem( "saveas", "#AssetBuilder_FileSaveAs", new KeyValues( "FileSaveAs" ), this );
+ SetSysMenu( pMenu );
+
+ m_pFileOpenStateMachine = new vgui::FileOpenStateMachine( this, this );
+ m_pFileOpenStateMachine->AddActionSignalTarget( this );
+
+ // Load layout settings; has to happen before pinning occurs in code
+ LoadControlSettingsAndUserConfig( "resource/assetbuilderframe.res" );
+
+ UpdateFileName();
+}
+
+CAssetBuilderFrame::~CAssetBuilderFrame()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Inherited from IFileOpenStateMachineClient
+//-----------------------------------------------------------------------------
+void CAssetBuilderFrame::SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues )
+{
+ // Compute starting directory
+ char pStartingDir[ MAX_PATH ];
+ GetModContentSubdirectory( "", pStartingDir, sizeof(pStartingDir) );
+
+ if ( bOpenFile )
+ {
+ // Clear out the existing makefile if we're opening a file
+ m_pAssetBuilder->SetRootMakefile( NULL );
+ pDialog->SetTitle( "Open Asset MakeFile", true );
+ }
+ else
+ {
+ pDialog->SetTitle( "Save Asset MakeFile As", true );
+ }
+
+ pDialog->SetStartDirectoryContext( "asset_browser_makefile", pStartingDir );
+ pDialog->AddFilter( "*.*", "All Files (*.*)", false );
+ pDialog->AddFilter( "*.dmx", "Asset MakeFiles (*.dmx)", true, "keyvalues2" );
+}
+
+bool CAssetBuilderFrame::OnReadFileFromDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues )
+{
+ CDmElement *pRoot;
+ CDmeMakefile *pMakeFile = ReadMakefile( pFileName, &pRoot );
+ if ( !pMakeFile )
+ return false;
+
+ Reset( pMakeFile );
+ return true;
+}
+
+bool CAssetBuilderFrame::OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues )
+{
+ // Recompute relative paths for each source now that we know the file name
+ // NOTE: This also updates the name of the fileID in the datamodel system
+ CDmeMakefile *pMakefile = m_pAssetBuilder->GetMakeFile();
+ bool bOk;
+ {
+ CDisableUndoScopeGuard guard;
+ bOk = pMakefile->SetFileName( pFileName );
+ }
+ if ( !bOk )
+ {
+ vgui::MessageBox *pError = new vgui::MessageBox( "#AssetBuilder_CannotRenameSourceFiles", "#AssetBuilder_CannotRenameSourceFilesText", this );
+ pError->DoModal();
+ return false;
+ }
+
+ CDmElement *pRoot = GetElement< CDmElement >( g_pDataModel->GetFileRoot( pMakefile->GetFileId() ) );
+ if ( !pRoot )
+ {
+ pRoot = pMakefile;
+ }
+ bOk = g_pDataModel->SaveToFile( pFileName, NULL, g_pDataModel->GetDefaultEncoding( pFileFormat ), pFileFormat, pRoot );
+ m_pAssetBuilder->Refresh();
+ return bOk;
+}
+
+
+//-----------------------------------------------------------------------------
+// Updates the file name
+//-----------------------------------------------------------------------------
+void CAssetBuilderFrame::UpdateFileName( )
+{
+ CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
+ if ( !pMakeFile )
+ {
+ SetTitle( m_TitleString.Get(), true );
+ return;
+ }
+
+ DmeMakefileType_t *pMakefileType = pMakeFile->GetMakefileType();
+
+ DmFileId_t fileId = pMakeFile->GetFileId();
+ const char *pFileName = ( fileId != DMFILEID_INVALID ) ? g_pDataModel->GetFileName( fileId ) : "<unnamed>";
+ if ( !pFileName || !pFileName[0] )
+ {
+ pFileName = "<unnamed>";
+ }
+
+ char pBuf[2*MAX_PATH];
+ if ( m_TitleString.Get() )
+ {
+ Q_snprintf( pBuf, sizeof(pBuf), "%s - %s - %s%s", m_TitleString.Get(), pMakefileType->m_pHumanReadableName, pFileName, pMakeFile->IsDirty() ? " *" : "" );
+ }
+ else
+ {
+ Q_snprintf( pBuf, sizeof(pBuf), "%s - %s%s", pMakefileType->m_pHumanReadableName, pFileName, pMakeFile->IsDirty() ? " *" : "" );
+ }
+ SetTitle( pBuf, true );
+}
+
+
+//-----------------------------------------------------------------------------
+// Marks the file as dirty (or not)
+//-----------------------------------------------------------------------------
+void CAssetBuilderFrame::SetDirty( bool bDirty )
+{
+ CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
+ if ( pMakeFile && ( pMakeFile->IsDirty() != bDirty ) )
+ {
+ pMakeFile->SetDirty( bDirty );
+
+ // Necessary because we draw a * if it's dirty before the name
+ UpdateFileName();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the asset builder changes something
+//-----------------------------------------------------------------------------
+void CAssetBuilderFrame::OnDmeElementChanged()
+{
+ SetDirty( true );
+}
+
+
+//-----------------------------------------------------------------------------
+// Resets the state
+//-----------------------------------------------------------------------------
+void CAssetBuilderFrame::Reset( CDmeMakefile *pMakeFile )
+{
+ // NOTE: Don't need to call SetDirty because we call UpdateFileName below
+ m_pAssetBuilder->SetRootMakefile( pMakeFile );
+ UpdateFileName();
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the file open dialog for selecting the new asset name is selected
+//-----------------------------------------------------------------------------
+void CAssetBuilderFrame::OnPerformFileNew( KeyValues *kv )
+{
+ const char *pMakefileType = kv->GetString( "makefileType" );
+ const char *pFileName = kv->GetString( "fileName" );
+ CDmeMakefile *pMakeFile;
+ {
+ DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( pFileName );
+ CDisableUndoScopeGuard guard;
+ pMakeFile = CreateElement< CDmeMakefile >( pMakefileType, pFileName, fileid );
+ }
+ if ( !pMakeFile )
+ return;
+
+ pMakeFile->SetFileName( pFileName );
+ Reset( pMakeFile );
+ SetDirty( true );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called when the file open dialog for browsing source files selects something
+//-----------------------------------------------------------------------------
+void CAssetBuilderFrame::OnFileSelected( KeyValues *kv )
+{
+ const char *pFileName = kv->GetString( "fullpath", NULL );
+ if ( !pFileName )
+ return;
+
+ KeyValues *pDialogKeys = kv->FindKey( "OnFileNew" );
+ if ( pDialogKeys )
+ {
+ KeyValues *pOkCommand = new KeyValues( "PerformFileNew", "makefileType", pDialogKeys->GetString( "makefileType" ) );
+ pOkCommand->SetString( "fileName", pFileName );
+ OverwriteFileDialog( this, pFileName, pOkCommand );
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by the picker popped up in OnFileNew
+//-----------------------------------------------------------------------------
+void CAssetBuilderFrame::OnPicked( KeyValues *kv )
+{
+ const char *pValue = kv->GetString( "choice" );
+
+ CDisableUndoScopeGuard guard;
+ CDmeMakefile *pMakeFile = GetElement< CDmeMakefile >( g_pDataModel->CreateElement( pValue, "unnamed" ) );
+ if ( !pMakeFile )
+ return;
+
+ DmeMakefileType_t *pType = pMakeFile->GetMakefileType();
+
+ char pContext[MAX_PATH];
+ Q_snprintf( pContext, sizeof(pContext), "asset_builder_session_%s", pType->m_pTypeName );
+
+ char pStartingDir[MAX_PATH];
+ pMakeFile->GetDefaultDirectory( pType->m_pDefaultDirectoryID, pStartingDir, sizeof(pStartingDir) );
+ g_pFullFileSystem->CreateDirHierarchy( pStartingDir );
+
+ char pTitle[MAX_PATH];
+ Q_snprintf( pTitle, sizeof(pTitle), "Select %s File Name", pType->m_pHumanReadableName );
+
+ KeyValues *pDialogKeys = new KeyValues( "OnFileNew", "makefileType", pValue );
+ FileOpenDialog *pDialog = new FileOpenDialog( this, pTitle, false, pDialogKeys );
+ pDialog->SetStartDirectoryContext( pContext, pStartingDir );
+ pDialog->AddFilter( pType->m_pFileFilter, pType->m_pFileFilterString, true );
+ pDialog->SetDeleteSelfOnClose( true );
+ pDialog->AddActionSignalTarget( this );
+ pDialog->DoModal( false );
+ DestroyElement( pMakeFile );
+}
+
+
+//-----------------------------------------------------------------------------
+// Called by the file open state machine when an operation has completed
+//-----------------------------------------------------------------------------
+void CAssetBuilderFrame::OnFileStateMachineFinished( KeyValues *pKeyValues )
+{
+ KeyValues *pNewFile = pKeyValues->FindKey( "FileNew" );
+ if ( pNewFile )
+ {
+ if ( pKeyValues->GetInt( "wroteFile", 0 ) != 0 )
+ {
+ SetDirty( false );
+ UpdateFileName();
+ }
+ if ( pKeyValues->GetInt( "completionState", FileOpenStateMachine::IN_PROGRESS ) == FileOpenStateMachine::SUCCESSFUL )
+ {
+ ShowNewAssetPicker();
+ }
+ return;
+ }
+
+ KeyValues *pSaveFile = pKeyValues->FindKey( "FileSave" );
+ if ( pSaveFile )
+ {
+ if ( pKeyValues->GetInt( "wroteFile", 0 ) != 0 )
+ {
+ SetDirty( false );
+ UpdateFileName();
+ }
+ return;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Shows a picker for creating a new asset
+//-----------------------------------------------------------------------------
+void CAssetBuilderFrame::ShowNewAssetPicker( )
+{
+ BuildAssetTypeList();
+
+ // Create a list indicating which type of asset to create
+ CPickerFrame *pPicker = new CPickerFrame( this, "Select Asset Type", "Asset Type", "assetType" );
+ pPicker->DoModal( s_AssetTypes );
+}
+
+
+//-----------------------------------------------------------------------------
+// Creates a new file
+//-----------------------------------------------------------------------------
+void CAssetBuilderFrame::OnFileNew( )
+{
+ CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
+ if ( pMakeFile && pMakeFile->IsDirty() )
+ {
+ KeyValues *pContextKeyValues = new KeyValues( "FileNew" );
+ const char *pFileName = g_pDataModel->GetFileName( pMakeFile->GetFileId() );
+ m_pFileOpenStateMachine->SaveFile( pContextKeyValues, pFileName, ASSET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY );
+ return;
+ }
+
+ ShowNewAssetPicker();
+}
+
+void CAssetBuilderFrame::OnFileOpen( )
+{
+ int nFlags = 0;
+ const char *pFileName = NULL;
+ CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
+ if ( pMakeFile && pMakeFile->IsDirty() )
+ {
+ nFlags = FOSM_SHOW_PERFORCE_DIALOGS | FOSM_SHOW_SAVE_QUERY;
+ pFileName = g_pDataModel->GetFileName( pMakeFile->GetFileId() );
+ }
+ KeyValues *pContextKeyValues = new KeyValues( "FileOpen" );
+ m_pFileOpenStateMachine->OpenFile( ASSET_FILE_FORMAT, pContextKeyValues, pFileName, NULL, nFlags );
+}
+
+void CAssetBuilderFrame::OnFileSave( )
+{
+ CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
+ if ( !pMakeFile )
+ return;
+
+ KeyValues *pContextKeyValues = new KeyValues( "FileSave" );
+ const char *pFileName = g_pDataModel->GetFileName( pMakeFile->GetFileId() );
+ m_pFileOpenStateMachine->SaveFile( pContextKeyValues, pFileName, ASSET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS );
+}
+
+void CAssetBuilderFrame::OnFileSaveAs( )
+{
+ CDmeMakefile *pMakeFile = m_pAssetBuilder->GetMakeFile();
+ if ( !pMakeFile )
+ return;
+
+ KeyValues *pContextKeyValues = new KeyValues( "FileSave" );
+ m_pFileOpenStateMachine->SaveFile( pContextKeyValues, NULL, ASSET_FILE_FORMAT, FOSM_SHOW_PERFORCE_DIALOGS );
+}
+
+