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 /movieobjects/dmemakefile.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'movieobjects/dmemakefile.cpp')
| -rw-r--r-- | movieobjects/dmemakefile.cpp | 628 |
1 files changed, 628 insertions, 0 deletions
diff --git a/movieobjects/dmemakefile.cpp b/movieobjects/dmemakefile.cpp new file mode 100644 index 0000000..3fc41ba --- /dev/null +++ b/movieobjects/dmemakefile.cpp @@ -0,0 +1,628 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Describes an asset: something that is compiled from sources, +// in potentially multiple steps, to a compiled resource +// +//============================================================================= + + +#include "movieobjects/dmemdlmakefile.h" +#include "movieobjects/idmemakefileutils.h" +#include "datamodel/dmelementfactoryhelper.h" +#include "tier2/fileutils.h" +#include "tier3/tier3.h" +#include "filesystem.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +//----------------------------------------------------------------------------- +// Hook into element factories +//----------------------------------------------------------------------------- +IMPLEMENT_ELEMENT_FACTORY( DmeSource, CDmeSource ); + + +//----------------------------------------------------------------------------- +// Construction/destruction +//----------------------------------------------------------------------------- +void CDmeSource::OnConstruction() +{ + m_DependentMakefile = NULL; +} + +void CDmeSource::OnDestruction() +{ +} + + +//----------------------------------------------------------------------------- +// Sets/gets the makefile that was used to build this source +//----------------------------------------------------------------------------- +void CDmeSource::SetDependentMakefile( CDmeMakefile *pMakeFile ) +{ + m_DependentMakefile = pMakeFile; +} + +CDmeMakefile *CDmeSource::GetDependentMakefile() +{ + return m_DependentMakefile.Get(); +} + + +//----------------------------------------------------------------------------- +// Call this to open the source file in an editor +//----------------------------------------------------------------------------- +void CDmeSource::OpenEditor() +{ + if ( g_pDmeMakefileUtils ) + { + g_pDmeMakefileUtils->PerformOpenEditor( this ); + } +} + + +//----------------------------------------------------------------------------- +// Hook into element factories +//----------------------------------------------------------------------------- +IMPLEMENT_ELEMENT_FACTORY( DmeMakefile, CDmeMakefile ); + + +//----------------------------------------------------------------------------- +// Construction/destruction +//----------------------------------------------------------------------------- +void CDmeMakefile::OnConstruction() +{ + m_Sources.Init( this, "sources" ); + m_hOutput = NULL; + m_hCompileProcess = PROCESS_HANDLE_INVALID; + m_bIsDirty = false; +} + +void CDmeMakefile::OnDestruction() +{ + DestroyOutputElement( m_hOutput.Get() ); + m_hOutput = NULL; +} + + +//----------------------------------------------------------------------------- +// Performs pre-compilation step +//----------------------------------------------------------------------------- +void CDmeMakefile::PreCompile( ) +{ + // Make all outputs writeable + MakeOutputsWriteable(); + + // Destroy the current output object; we'll need to reload it + // NOTE: Don't check for m_hOutput == 0; we always need to call DestroyOutputElement + // Sometimes makefiles have to do stuff even if m_hOutput == NULL + DestroyOutputElement( m_hOutput ); + m_hOutput = NULL; +} + +void CDmeMakefile::PostCompile( ) +{ +} + + +//----------------------------------------------------------------------------- +// Gets the output element created by compilation of this makefile +//----------------------------------------------------------------------------- +CDmElement *CDmeMakefile::GetOutputElement( bool bCreateIfNecessary ) +{ + if ( m_hOutput.Get() ) + return m_hOutput.Get(); + + if ( !bCreateIfNecessary ) + return NULL; + + if ( !g_pDmeMakefileUtils || !g_pDmeMakefileUtils->IsCurrentlyCompiling() ) + { + m_hOutput = CreateOutputElement(); + } + + return m_hOutput.Get(); +} + + +//----------------------------------------------------------------------------- +// Gets the path of the makefile +//----------------------------------------------------------------------------- +void CDmeMakefile::GetMakefilePath( char *pFullPath, int nBufLen ) +{ + DmFileId_t fileId = GetFileId(); + const char *pFileName = ( fileId != DMFILEID_INVALID ) ? g_pDataModel->GetFileName( fileId ) : ""; + Assert( !pFileName[0] || Q_IsAbsolutePath( pFileName ) ); + + Q_ExtractFilePath( pFileName, pFullPath, nBufLen ); +} + + +//----------------------------------------------------------------------------- +// Returns the output directory we expect to compile files into +//----------------------------------------------------------------------------- +bool CDmeMakefile::GetOutputDirectory( char *pFullPath, int nBufLen ) +{ + return GetDefaultDirectory( GetOutputDirectoryID(), pFullPath, nBufLen ); +} + + +//----------------------------------------------------------------------------- +// Returns the output name (output directory + filename, no extension) +//----------------------------------------------------------------------------- +bool CDmeMakefile::GetOutputName( char *pFullPath, int nBufLen ) +{ + pFullPath[0] = 0; + + char pOutputPath[MAX_PATH]; + if ( !GetDefaultDirectory( GetOutputDirectoryID(), pOutputPath, sizeof(pOutputPath) ) ) + return false; + + DmFileId_t fileId = GetFileId(); + const char *pFileName = ( fileId != DMFILEID_INVALID ) ? g_pDataModel->GetFileName( fileId ) : ""; + if ( !pFileName || !pFileName[0] ) + return false; + + Q_ComposeFileName( pOutputPath, Q_UnqualifiedFileName(pFileName), pFullPath, nBufLen ); + Q_RemoveDotSlashes( pFullPath ); + return true; +} + + +//----------------------------------------------------------------------------- +// Converts the m_pDefaultDirectoryID field of the DmeMakefileType_t to a full path +//----------------------------------------------------------------------------- +bool CDmeMakefile::GetDefaultDirectory( const char *pDefaultDirectoryID, char *pFullPath, int nBufLen ) +{ + if ( StringHasPrefix( pDefaultDirectoryID, "contentdir:" ) ) + { + pDefaultDirectoryID += 11; + GetModContentSubdirectory( pDefaultDirectoryID, pFullPath, nBufLen ); + Q_RemoveDotSlashes( pFullPath ); + return true; + } + + if ( StringHasPrefix( pDefaultDirectoryID, "gamedir:" ) ) + { + pDefaultDirectoryID += 8; + GetModSubdirectory( pDefaultDirectoryID, pFullPath, nBufLen ); + Q_RemoveDotSlashes( pFullPath ); + return true; + } + + if ( StringHasPrefix( pDefaultDirectoryID, "makefiledir:" ) ) + { + char pMakefilePath[MAX_PATH]; + GetMakefilePath( pMakefilePath, sizeof(pMakefilePath) ); + pDefaultDirectoryID += 12; + Q_ComposeFileName( pMakefilePath, pDefaultDirectoryID, pFullPath, nBufLen ); + Q_RemoveDotSlashes( pFullPath ); + return true; + } + + if ( StringHasPrefix( pDefaultDirectoryID, "makefilegamedir:" ) ) + { + char pMakefilePath[MAX_PATH]; + GetMakefilePath( pMakefilePath, sizeof(pMakefilePath) ); + + char pModContentDirectory[MAX_PATH]; + GetModContentSubdirectory( NULL, pModContentDirectory, sizeof(pModContentDirectory) ); + + char pRelativePath[MAX_PATH]; + if ( !Q_MakeRelativePath( pMakefilePath, pModContentDirectory, pRelativePath, sizeof(pRelativePath) ) ) + { + pFullPath[0] = 0; + return false; + } + + char pModDirectory[MAX_PATH]; + GetModSubdirectory( NULL, pModDirectory, sizeof(pModDirectory) ); + + char pMakefileGamePath[MAX_PATH]; + Q_ComposeFileName( pModDirectory, pRelativePath, pMakefileGamePath, sizeof(pMakefileGamePath) ); + + pDefaultDirectoryID += 16; + Q_ComposeFileName( pMakefileGamePath, pDefaultDirectoryID, pFullPath, nBufLen ); + Q_RemoveDotSlashes( pFullPath ); + return true; + } + + // Assume it's a content subdir + GetModContentSubdirectory( pDefaultDirectoryID, pFullPath, nBufLen ); + Q_RemoveDotSlashes( pFullPath ); + return true; +} + + +//----------------------------------------------------------------------------- +// Relative path to full path +//----------------------------------------------------------------------------- +void CDmeMakefile::RelativePathToFullPath( const char *pRelativePath, char *pFullPath, int nBufLen ) +{ + if ( !pRelativePath[0] ) + { + pFullPath[0] = 0; + return; + } + char pRootDir[ MAX_PATH ]; + GetMakefilePath( pRootDir, sizeof(pRootDir) ); + Q_ComposeFileName( pRootDir, pRelativePath, pFullPath, nBufLen ); + Q_RemoveDotSlashes( pFullPath ); +} + + +//----------------------------------------------------------------------------- +// Fullpath to relative path +//----------------------------------------------------------------------------- +void CDmeMakefile::FullPathToRelativePath( const char *pFullPath, char *pRelativePath, int nBufLen ) +{ + if ( !pFullPath[0] ) + { + pRelativePath[0] = 0; + return; + } + char pRootDir[ MAX_PATH ]; + GetMakefilePath( pRootDir, sizeof(pRootDir) ); + if ( pRootDir[0] ) + { + Q_MakeRelativePath( pFullPath, pRootDir, pRelativePath, nBufLen ); + } + else + { + Q_strncpy( pRelativePath, pFullPath, nBufLen ); + Q_FixSlashes( pRelativePath ); + } +} + + +//----------------------------------------------------------------------------- +// Adds a single source +//----------------------------------------------------------------------------- +CDmeSource *CDmeMakefile::AddSource( const char *pSourceType, const char *pFullPath ) +{ + if ( pFullPath[0] && FindSource( pSourceType, pFullPath ) ) + { + Warning( "Attempted to add the same source twice %s!\n", pFullPath ); + return NULL; + } + + CDmElement *pElement = GetElement< CDmElement >( g_pDataModel->CreateElement( pSourceType, "", GetFileId() ) ); + CDmeSource *pSource = CastElement< CDmeSource >( pElement ); + Assert( pSource ); + if ( !pSource ) + { + Warning( "Invalid source type name %s!\n", pSourceType ); + if ( pElement ) + { + DestroyElement( pElement ); + } + return NULL; + } + + char pRelativePath[MAX_PATH]; + FullPathToRelativePath( pFullPath, pRelativePath, sizeof( pRelativePath ) ); + pSource->SetRelativeFileName( pRelativePath ); + m_Sources.AddToTail( pSource ); + return pSource; +} + + +//----------------------------------------------------------------------------- +// Removes a single source +//----------------------------------------------------------------------------- +CDmeSource *CDmeMakefile::FindSource( const char *pSourceType, const char *pFullPath ) +{ + char pRelativePath[MAX_PATH]; + FullPathToRelativePath( pFullPath, pRelativePath, sizeof( pRelativePath ) ); + int nCount = m_Sources.Count(); + for ( int i = 0; i < nCount; ++i ) + { + if ( Q_stricmp( pSourceType, m_Sources[i]->GetTypeString() ) ) + continue; + + if ( !Q_stricmp( pRelativePath, m_Sources[i]->GetRelativeFileName() ) ) + return m_Sources[i]; + } + return NULL; +} + + +//----------------------------------------------------------------------------- +// Sets a source to be a single source +//----------------------------------------------------------------------------- +CDmeSource *CDmeMakefile::SetSingleSource( const char *pSourceType, const char *pFullPath ) +{ + // FIXME: we maybe shouldn't remove everything if the source can't be created for some reason? + RemoveAllSources( pSourceType ); + return AddSource( pSourceType, pFullPath ); +} + + +//----------------------------------------------------------------------------- +// Changes a source +//----------------------------------------------------------------------------- +void CDmeMakefile::SetSourceFullPath( CDmeSource *pSource, const char *pFullPath ) +{ + char pRelativePath[MAX_PATH]; + FullPathToRelativePath( pFullPath, pRelativePath, sizeof( pRelativePath ) ); + + if ( Q_stricmp( pRelativePath, pSource->GetRelativeFileName() ) ) + { + pSource->SetRelativeFileName( pRelativePath ); + + // FIXME: Should we delete the dependent makefile? + pSource->SetDependentMakefile( NULL ); + } +} + + +//----------------------------------------------------------------------------- +// Returns the full path of a source +//----------------------------------------------------------------------------- +void CDmeMakefile::GetSourceFullPath( CDmeSource *pSource, char *pFullPath, int nBufLen ) +{ + const char *pRelativePath = pSource->GetRelativeFileName( ); + RelativePathToFullPath( pRelativePath, pFullPath, nBufLen ); +} + + +//----------------------------------------------------------------------------- +// Returns a list of sources +//----------------------------------------------------------------------------- +void CDmeMakefile::GetSources( const char *pSourceType, CUtlVector< CDmeHandle< CDmeSource > > &sources ) +{ + int nCount = m_Sources.Count(); + sources.EnsureCapacity( nCount ); + for ( int i = 0; i < nCount; ++i ) + { + if ( m_Sources[i]->IsA( pSourceType ) ) + { + int j = sources.AddToTail(); + sources[j] = m_Sources[i]; + } + } +} + + +//----------------------------------------------------------------------------- +// Gets a list of all sources, regardless of type +//----------------------------------------------------------------------------- +int CDmeMakefile::GetSourceCount() +{ + return m_Sources.Count(); +} + +CDmeSource *CDmeMakefile::GetSource( int nIndex ) +{ + return m_Sources[nIndex]; +} + + +//----------------------------------------------------------------------------- +// Removes a single source +//----------------------------------------------------------------------------- +void CDmeMakefile::RemoveSource( CDmeSource *pSource ) +{ + int nCount = m_Sources.Count(); + for ( int i = 0; i < nCount; ++i ) + { + if ( m_Sources[i] == pSource ) + { + m_Sources.Remove( i ); + break; + } + } +} + +void CDmeMakefile::RemoveSource( const char *pSourceType, const char *pFullPath ) +{ + char pRelativePath[MAX_PATH]; + FullPathToRelativePath( pFullPath, pRelativePath, sizeof( pRelativePath ) ); + int nCount = m_Sources.Count(); + for ( int i = 0; i < nCount; ++i ) + { + if ( Q_stricmp( pSourceType, m_Sources[i]->GetTypeString() ) ) + continue; + + if ( !Q_stricmp( pRelativePath, m_Sources[i]->GetRelativeFileName() ) ) + { + m_Sources.Remove( i ); + break; + } + } +} + + +//----------------------------------------------------------------------------- +// Removes all sources of a particular type +//----------------------------------------------------------------------------- +void CDmeMakefile::RemoveAllSources( const char *pSourceType ) +{ + int nCount = m_Sources.Count(); + for ( int i = nCount; --i >= 0; ) + { + if ( !Q_stricmp( pSourceType, m_Sources[i]->GetTypeString() ) ) + { + // NOTE: This works because we're iterating backward + m_Sources.Remove( i ); + } + } +} + + +//----------------------------------------------------------------------------- +// Source iteration +//----------------------------------------------------------------------------- +bool CDmeMakefile::HasSourceOfType( const char *pSourceType ) +{ + int nCount = m_Sources.Count(); + for ( int i = nCount; --i >= 0; ) + { + if ( !Q_stricmp( pSourceType, m_Sources[i]->GetTypeString() ) ) + return true; + } + return false; +} + + +//----------------------------------------------------------------------------- +// Updates the source names to be relative to a particular path +//----------------------------------------------------------------------------- +bool CDmeMakefile::UpdateSourceNames( const char *pOldRootDir, const char *pNewRootDir, bool bApplyChanges ) +{ + char pOldSourcePath[ MAX_PATH ]; + char pNewSourcePath[ MAX_PATH ]; + + int nCount = m_Sources.Count(); + for ( int i = 0; i < nCount; ++i ) + { + const char *pOldRelativePath = m_Sources[i]->GetRelativeFileName(); + if ( pOldRelativePath[0] ) + { + Q_ComposeFileName( pOldRootDir, pOldRelativePath, pOldSourcePath, sizeof(pOldSourcePath) ); + Q_RemoveDotSlashes( pOldSourcePath ); + if ( !Q_MakeRelativePath( pOldSourcePath, pNewRootDir, pNewSourcePath, sizeof(pNewSourcePath) ) ) + { + Assert( !bApplyChanges ); + return false; + } + } + else + { + pNewSourcePath[0] = 0; + } + + if ( !bApplyChanges ) + continue; + + m_Sources[i]->SetRelativeFileName( pNewSourcePath ); + } + return true; +} + + +//----------------------------------------------------------------------------- +// Returns the filename +//----------------------------------------------------------------------------- +const char *CDmeMakefile::GetFileName() const +{ + DmFileId_t fileId = GetFileId(); + return g_pDataModel->GetFileName( fileId ); +} + + +//----------------------------------------------------------------------------- +// Call this to change the file the makefile is stored in +// Will make all sources be relative to this path +//----------------------------------------------------------------------------- +bool CDmeMakefile::SetFileName( const char *pFileName ) +{ + if ( !Q_IsAbsolutePath( pFileName ) ) + return false; + + char pOldRootDir[ MAX_PATH ]; + char pNewRootDir[ MAX_PATH ]; + GetMakefilePath( pOldRootDir, sizeof(pOldRootDir) ); + Q_ExtractFilePath( pFileName, pNewRootDir, sizeof(pNewRootDir) ); + + // Gotta do this twice; once to check for validity, once to actually do it + if ( !UpdateSourceNames( pOldRootDir, pNewRootDir, false ) ) + return false; + + UpdateSourceNames( pOldRootDir, pNewRootDir, true ); + + DmFileId_t fileId = GetFileId(); + if ( fileId == DMFILEID_INVALID ) + { + fileId = g_pDataModel->FindOrCreateFileId( pFileName ); + SetFileId( fileId, TD_DEEP ); + } + else + { + g_pDataModel->SetFileName( fileId, pFileName ); + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Make all outputs writeable +//----------------------------------------------------------------------------- +void CDmeMakefile::MakeOutputsWriteable( ) +{ + // When we publish, we'll check them out. + CUtlVector<CUtlString> outputs; + GetOutputs( outputs ); + int nCount = outputs.Count(); + for ( int i = 0; i < nCount; ++i ) + { + g_pFullFileSystem->SetFileWritable( outputs[i], true ); + } +} + + + +//----------------------------------------------------------------------------- +// Sets a makefile/source association +//----------------------------------------------------------------------------- +void CDmeMakefile::SetAssociation( CDmeSource *pSource, CDmeMakefile *pSourceMakefile ) +{ + if ( !pSource ) + return; + + int nCount = m_Sources.Count(); + for ( int i = 0; i < nCount; ++i ) + { + if ( m_Sources[i] != pSource ) + continue; + + CDmeMakefile *pDependentMakeFile = m_Sources[i]->GetDependentMakefile(); + if ( pSourceMakefile != pDependentMakeFile ) + { + // FIXME: Should I recursively delete pDependentMakeFile ? + m_Sources[i]->SetDependentMakefile( pSourceMakefile ); + } + return; + } +} + + +//----------------------------------------------------------------------------- +// Finds a dependent makefile +//----------------------------------------------------------------------------- +CDmeMakefile *CDmeMakefile::FindDependentMakefile( CDmeSource *pSource ) +{ + if ( !pSource ) + return NULL; + + int nCount = m_Sources.Count(); + for ( int i = 0; i < nCount; ++i ) + { + if ( m_Sources[i] == pSource ) + return m_Sources[i]->GetDependentMakefile(); + } + + return NULL; +} + + +//----------------------------------------------------------------------------- +// Finds the associated source +//----------------------------------------------------------------------------- +CDmeSource *CDmeMakefile::FindAssociatedSource( CDmeMakefile *pChildMakefile ) +{ + if ( !pChildMakefile ) + return NULL; + + int nCount = m_Sources.Count(); + for ( int i = 0; i < nCount; ++i ) + { + if ( m_Sources[i]->GetDependentMakefile() == pChildMakefile ) + return m_Sources[i]; + } + + return NULL; +} + |