diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /vgui2/dme_controls/AssetBuilder.cpp | |
| download | archived-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.cpp | 1725 |
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 ); +} + + |