You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
630 lines
18 KiB
630 lines
18 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
// |
|
//=============================================================================// |
|
|
|
#include "vcdblockdoc.h" |
|
#include "tier1/KeyValues.h" |
|
#include "tier1/utlbuffer.h" |
|
#include "toolutils/enginetools_int.h" |
|
#include "filesystem.h" |
|
#include "vcdblocktool.h" |
|
#include "toolframework/ienginetool.h" |
|
#include "dmevmfentity.h" |
|
#include "datamodel/idatamodel.h" |
|
#include "toolutils/attributeelementchoicelist.h" |
|
#include "infotargetbrowserpanel.h" |
|
#include "vgui_controls/messagebox.h" |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Constructor |
|
//----------------------------------------------------------------------------- |
|
CVcdBlockDoc::CVcdBlockDoc( IVcdBlockDocCallback *pCallback ) : m_pCallback( pCallback ) |
|
{ |
|
m_hVMFRoot = NULL; |
|
m_hEditRoot = NULL; |
|
m_pBSPFileName[0] = 0; |
|
m_pVMFFileName[0] = 0; |
|
m_pEditFileName[0] = 0; |
|
m_bDirty = false; |
|
g_pDataModel->InstallNotificationCallback( this ); |
|
} |
|
|
|
CVcdBlockDoc::~CVcdBlockDoc() |
|
{ |
|
g_pDataModel->RemoveNotificationCallback( this ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Inherited from INotifyUI |
|
//----------------------------------------------------------------------------- |
|
void CVcdBlockDoc::NotifyDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags ) |
|
{ |
|
OnDataChanged( pReason, nNotifySource, nNotifyFlags ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Gets the file name |
|
//----------------------------------------------------------------------------- |
|
const char *CVcdBlockDoc::GetBSPFileName() |
|
{ |
|
return m_pBSPFileName; |
|
} |
|
|
|
const char *CVcdBlockDoc::GetVMFFileName() |
|
{ |
|
return m_pVMFFileName; |
|
} |
|
|
|
void CVcdBlockDoc::SetVMFFileName( const char *pFileName ) |
|
{ |
|
Q_strncpy( m_pVMFFileName, pFileName, sizeof( m_pVMFFileName ) ); |
|
Q_FixSlashes( m_pVMFFileName ); |
|
SetDirty( true ); |
|
} |
|
|
|
const char *CVcdBlockDoc::GetEditFileName() |
|
{ |
|
return m_pEditFileName; |
|
} |
|
|
|
void CVcdBlockDoc::SetEditFileName( const char *pFileName ) |
|
{ |
|
Q_strncpy( m_pEditFileName, pFileName, sizeof( m_pEditFileName ) ); |
|
Q_FixSlashes( m_pEditFileName ); |
|
SetDirty( true ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Dirty bits |
|
//----------------------------------------------------------------------------- |
|
void CVcdBlockDoc::SetDirty( bool bDirty ) |
|
{ |
|
m_bDirty = bDirty; |
|
} |
|
|
|
bool CVcdBlockDoc::IsDirty() const |
|
{ |
|
return m_bDirty; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Saves/loads from file |
|
//----------------------------------------------------------------------------- |
|
bool CVcdBlockDoc::LoadFromFile( const char *pFileName ) |
|
{ |
|
Assert( !m_hVMFRoot.Get() ); |
|
Assert( !m_hEditRoot.Get() ); |
|
|
|
CAppDisableUndoScopeGuard guard( "CVcdBlockDoc::LoadFromFile", NOTIFY_CHANGE_OTHER ); |
|
SetDirty( false ); |
|
|
|
if ( !pFileName[0] ) |
|
return false; |
|
|
|
// Construct VMF file name from the BSP |
|
const char *pGame = Q_stristr( pFileName, "\\game\\" ); |
|
if ( !pGame ) |
|
{ |
|
pGame = Q_stristr( pFileName, "\\content\\" ); |
|
if ( !pGame ) |
|
return false; |
|
} |
|
|
|
// Compute the map name |
|
const char *pMaps = Q_stristr( pFileName, "\\maps\\" ); |
|
if ( !pMaps ) |
|
return false; |
|
|
|
// Build map name |
|
char mapname[ 256 ]; |
|
Q_StripExtension( pFileName, mapname, sizeof(mapname) ); |
|
char *pszFileName = (char*)Q_UnqualifiedFileName(mapname); |
|
|
|
int nLen = (int)( (size_t)pGame - (size_t)pFileName ) + 1; |
|
Q_strncpy( m_pVMFFileName, pFileName, nLen ); |
|
Q_strncat( m_pVMFFileName, "\\content\\", sizeof(m_pVMFFileName) ); |
|
Q_strncat( m_pVMFFileName, pGame + 6, sizeof(m_pVMFFileName) ); |
|
Q_SetExtension( m_pVMFFileName, ".vmf", sizeof(m_pVMFFileName) ); |
|
|
|
// Make sure new entities start with ids at 0 |
|
CDmeVMFEntity::SetNextEntityId( 0 ); |
|
|
|
// Build the Edit file name |
|
Q_StripExtension( m_pVMFFileName, m_pEditFileName, sizeof(m_pEditFileName) ); |
|
Q_strncat( m_pEditFileName, ".vle", sizeof( m_pEditFileName ) ); |
|
|
|
// Store the BSP file name |
|
Q_strncpy( m_pBSPFileName, pFileName, sizeof( m_pBSPFileName ) ); |
|
|
|
// Set the txt file name. |
|
// If we loaded a .bsp, clear out what we're doing |
|
// load the Edits file into memory, assign it as our "root" |
|
CDmElement *pEdit = NULL; |
|
if ( !V_stricmp( Q_GetFileExtension( pFileName ), "vle" ) ) |
|
{ |
|
if ( g_pDataModel->RestoreFromFile( m_pEditFileName, NULL, "vmf", &pEdit ) != DMFILEID_INVALID ) |
|
{ |
|
// If we successfully read the file in, ask it for the max hammer id |
|
//int nMaxHammerId = pVMF->GetAttributeValue<int>( "maxHammerId" ); |
|
//CDmeVMFEntity::SetNextEntityId( nMaxHammerId + 1 ); |
|
m_hEditRoot = pEdit; |
|
SetDirty( false ); |
|
} |
|
} |
|
|
|
if (pEdit == NULL) |
|
{ |
|
if ( g_pFileSystem->FileExists( m_pEditFileName ) ) |
|
{ |
|
char pBuf[1024]; |
|
Q_snprintf( pBuf, sizeof(pBuf), "File %s already exists!\n", m_pEditFileName ); |
|
m_pEditFileName[0] = 0; |
|
vgui::MessageBox *pMessageBox = new vgui::MessageBox( "Unable to overwrite file!\n", pBuf, g_pVcdBlockTool ); |
|
pMessageBox->DoModal( ); |
|
return false; |
|
} |
|
|
|
DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( m_pEditFileName ); |
|
m_hEditRoot = CreateElement<CDmElement>( "root", fileid ); |
|
m_hEditRoot->AddAttribute( "entities", AT_ELEMENT_ARRAY ); |
|
g_pDataModel->SetFileRoot( fileid, m_hEditRoot ); |
|
SetDirty( true ); |
|
} |
|
|
|
guard.Release(); |
|
|
|
// tell the engine to actually load the map |
|
char cmd[ 256 ]; |
|
Q_snprintf( cmd, sizeof( cmd ), "disconnect; map %s\n", pszFileName ); |
|
enginetools->Command( cmd ); |
|
enginetools->Execute( ); |
|
|
|
return true; |
|
} |
|
|
|
|
|
void CVcdBlockDoc::SaveToFile( ) |
|
{ |
|
if ( m_hEditRoot.Get() && m_pEditFileName && m_pEditFileName[0] ) |
|
{ |
|
g_pDataModel->SaveToFile( m_pEditFileName, NULL, "keyvalues", "vmf", m_hEditRoot ); |
|
} |
|
|
|
SetDirty( false ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Returns the root object |
|
//----------------------------------------------------------------------------- |
|
CDmElement *CVcdBlockDoc::GetRootObject() |
|
{ |
|
return m_hEditRoot; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Returns the entity list |
|
//----------------------------------------------------------------------------- |
|
CDmAttribute *CVcdBlockDoc::GetEntityList() |
|
{ |
|
return m_hEditRoot ? m_hEditRoot->GetAttribute( "entities", AT_ELEMENT_ARRAY ) : NULL; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CVcdBlockDoc::AddNewInfoTarget( const Vector &vecOrigin, const QAngle &angAngles ) |
|
{ |
|
CDmrElementArray<> entities = GetEntityList(); |
|
|
|
CDmeVMFEntity *pTarget; |
|
{ |
|
CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Add Info Target", "Add Info Target" ); |
|
|
|
pTarget = CreateElement<CDmeVMFEntity>( "", entities.GetOwner()->GetFileId() ); |
|
pTarget->SetValue( "classname", "info_target" ); |
|
pTarget->SetRenderOrigin( vecOrigin ); |
|
pTarget->SetRenderAngles( angAngles ); |
|
|
|
entities.AddToTail( pTarget ); |
|
pTarget->MarkDirty(); |
|
pTarget->DrawInEngine( true ); |
|
} |
|
|
|
g_pVcdBlockTool->GetInfoTargetBrowser()->SelectNode( pTarget ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CVcdBlockDoc::AddNewInfoTarget( void ) |
|
{ |
|
Vector vecOrigin; |
|
QAngle angAngles; |
|
float flFov; |
|
clienttools->GetLocalPlayerEyePosition( vecOrigin, angAngles, flFov ); |
|
AddNewInfoTarget( vecOrigin, vec3_angle ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Deletes a commentary node |
|
//----------------------------------------------------------------------------- |
|
void CVcdBlockDoc::DeleteInfoTarget( CDmeVMFEntity *pNode ) |
|
{ |
|
CDmrElementArray<CDmElement> entities = GetEntityList(); |
|
int nCount = entities.Count(); |
|
for ( int i = 0; i < nCount; ++i ) |
|
{ |
|
if ( pNode == entities[i] ) |
|
{ |
|
CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Delete Info Target", "Delete Info Target" ); |
|
CDmeVMFEntity *pNode = CastElement< CDmeVMFEntity >( entities[ i ] ); |
|
pNode->DrawInEngine( false ); |
|
entities.FastRemove( i ); |
|
return; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : &vecOrigin - |
|
// &angAbsAngles - |
|
// Output : CDmeVMFEntity |
|
//----------------------------------------------------------------------------- |
|
CDmeVMFEntity *CVcdBlockDoc::GetInfoTargetForLocation( Vector &vecOrigin, QAngle &angAbsAngles ) |
|
{ |
|
const CDmrElementArray<> entities = GetEntityList(); |
|
int nCount = entities.Count(); |
|
for ( int i = 0; i < nCount; ++i ) |
|
{ |
|
CDmeVMFEntity *pNode = CastElement< CDmeVMFEntity >( entities[ i ] ); |
|
Vector &vecAngles = *(Vector*)(&pNode->GetRenderAngles()); |
|
if ( pNode->GetRenderOrigin().DistTo( vecOrigin ) < 1e-3 && vecAngles.DistTo( *(Vector*)&angAbsAngles ) < 1e-1 ) |
|
return pNode; |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : &vecStart - |
|
// &vecEnd - |
|
// Output : CDmeVMFEntity |
|
//----------------------------------------------------------------------------- |
|
CDmeVMFEntity *CVcdBlockDoc::GetInfoTargetForLocation( Vector &vecStart, Vector &vecEnd ) |
|
{ |
|
Vector vecDelta; |
|
float flEndDist; |
|
|
|
vecDelta = vecEnd - vecStart; |
|
flEndDist = VectorNormalize( vecDelta ); |
|
|
|
CDmeVMFEntity *pSelectedNode = NULL; |
|
float flMinDistFromLine = 1E30; |
|
|
|
const CDmrElementArray<CDmElement> entities = GetEntityList(); |
|
int nCount = entities.Count(); |
|
for ( int i = 0; i < nCount; ++i ) |
|
{ |
|
CDmeVMFEntity *pNode = CastElement< CDmeVMFEntity >( entities[ i ] ); |
|
float flDistAway = DotProduct( pNode->GetRenderOrigin() - vecStart, vecDelta ); |
|
|
|
if (flDistAway > 0.0 && flDistAway < flEndDist) |
|
{ |
|
float flDistFromLine = (pNode->GetRenderOrigin() - vecStart - vecDelta * flDistAway).Length(); |
|
if (flDistFromLine < flMinDistFromLine) |
|
{ |
|
pSelectedNode = pNode; |
|
flMinDistFromLine = flDistFromLine; |
|
} |
|
} |
|
} |
|
return pSelectedNode; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Populate string choice lists |
|
//----------------------------------------------------------------------------- |
|
bool CVcdBlockDoc::GetStringChoiceList( const char *pChoiceListType, CDmElement *pElement, |
|
const char *pAttributeName, bool bArrayElement, StringChoiceList_t &list ) |
|
{ |
|
if ( !Q_stricmp( pChoiceListType, "info_targets" ) ) |
|
{ |
|
const CDmrElementArray<> entities = GetEntityList(); |
|
|
|
StringChoice_t sChoice; |
|
sChoice.m_pValue = ""; |
|
sChoice.m_pChoiceString = ""; |
|
list.AddToTail( sChoice ); |
|
|
|
int nCount = entities.Count(); |
|
for ( int i = 0; i < nCount; ++i ) |
|
{ |
|
CDmeVMFEntity *pNode = CastElement< CDmeVMFEntity >( entities[ i ] ); |
|
if ( !V_stricmp( pNode->GetClassName(), "info_target" ) ) |
|
{ |
|
StringChoice_t sChoice; |
|
sChoice.m_pValue = pNode->GetTargetName(); |
|
sChoice.m_pChoiceString = pNode->GetTargetName(); |
|
list.AddToTail( sChoice ); |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Populate element choice lists |
|
//----------------------------------------------------------------------------- |
|
bool CVcdBlockDoc::GetElementChoiceList( const char *pChoiceListType, CDmElement *pElement, |
|
const char *pAttributeName, bool bArrayElement, ElementChoiceList_t &list ) |
|
{ |
|
if ( !Q_stricmp( pChoiceListType, "allelements" ) ) |
|
{ |
|
AddElementsRecursively( m_hEditRoot, list ); |
|
return true; |
|
} |
|
|
|
if ( !Q_stricmp( pChoiceListType, "info_targets" ) ) |
|
{ |
|
const CDmrElementArray<> entities = GetEntityList(); |
|
|
|
bool bFound = false; |
|
int nCount = entities.Count(); |
|
for ( int i = 0; i < nCount; ++i ) |
|
{ |
|
CDmeVMFEntity *pNode = CastElement< CDmeVMFEntity >( entities[ i ] ); |
|
if ( !V_stricmp( pNode->GetClassName(), "info_target" ) ) |
|
{ |
|
bFound = true; |
|
ElementChoice_t sChoice; |
|
sChoice.m_pValue = pNode; |
|
sChoice.m_pChoiceString = pNode->GetTargetName(); |
|
list.AddToTail( sChoice ); |
|
} |
|
} |
|
return bFound; |
|
} |
|
|
|
// by default, try to treat the choice list type as a Dme element type |
|
AddElementsRecursively( m_hEditRoot, list, pChoiceListType ); |
|
|
|
return list.Count() > 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Called when data changes |
|
//----------------------------------------------------------------------------- |
|
void CVcdBlockDoc::OnDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags ) |
|
{ |
|
SetDirty( nNotifyFlags & NOTIFY_SETDIRTYFLAG ? true : false ); |
|
m_pCallback->OnDocChanged( pReason, nNotifySource, nNotifyFlags ); |
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// List of all entity classnames to copy over from the original block |
|
//----------------------------------------------------------------------------- |
|
static const char *s_pUseOriginalClasses[] = |
|
{ |
|
"worldspawn", |
|
"func_occluder", |
|
NULL |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// The server just loaded, populate the list with the entities is has |
|
//----------------------------------------------------------------------------- |
|
void CVcdBlockDoc::ServerLevelInitPostEntity( void ) |
|
{ |
|
CDmrElementArray<> entityList = GetEntityList(); |
|
|
|
if ( entityList.Count() ) |
|
{ |
|
VerifyAllEdits( entityList ); |
|
} |
|
else |
|
{ |
|
InitializeFromServer( entityList ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Create a list of entities based on what the server has |
|
//----------------------------------------------------------------------------- |
|
void CVcdBlockDoc::InitializeFromServer( CDmrElementArray<> &entityList ) |
|
{ |
|
CAppUndoScopeGuard guard( NOTIFY_SETDIRTYFLAG, "Initialize From Server" ); |
|
|
|
entityList.RemoveAll(); |
|
|
|
// initialize list with entities on the server |
|
CBaseEntity *pServerEnt = servertools->FirstEntity(); |
|
while (pServerEnt) |
|
{ |
|
char classname[256]; |
|
|
|
if (servertools->GetKeyValue( pServerEnt, "classname", classname, sizeof( classname ) ) ) |
|
{ |
|
if ( !Q_stricmp( classname, "info_target" )) |
|
{ |
|
char hammerid[256]; |
|
if ( servertools->GetKeyValue( pServerEnt, "hammerid", hammerid, sizeof( hammerid ) ) ) |
|
{ |
|
int nextId = CDmeVMFEntity::GetNextEntityId(); |
|
CDmeVMFEntity::SetNextEntityId( atoi( hammerid ) ); |
|
|
|
CDmeVMFEntity *pTarget = CreateElement<CDmeVMFEntity>( "", entityList.GetOwner()->GetFileId() ); |
|
|
|
CDmeVMFEntity::SetNextEntityId( nextId ); |
|
|
|
if ( pTarget->CopyFromServer( pServerEnt ) ) |
|
{ |
|
entityList.AddToTail( pTarget ); |
|
} |
|
} |
|
} |
|
} |
|
pServerEnt = servertools->NextEntity( pServerEnt ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Check the list of entities on the server against the edits that are already made |
|
//----------------------------------------------------------------------------- |
|
void CVcdBlockDoc::VerifyAllEdits( const CDmrElementArray<> &entityList ) |
|
{ |
|
// already filled in |
|
for (int i = 0; i < entityList.Count(); i++) |
|
{ |
|
CDmeVMFEntity *pEntity = CastElement<CDmeVMFEntity>( entityList[i] ); |
|
|
|
CBaseEntity *pServerEntity = servertools->FindEntityByHammerID( pEntity->GetEntityId() ); |
|
|
|
if (pServerEntity != NULL) |
|
{ |
|
if (!pEntity->IsSameOnServer( pServerEntity )) |
|
{ |
|
pEntity->MarkDirty(); |
|
} |
|
else |
|
{ |
|
pEntity->MarkDirty(false); |
|
} |
|
} |
|
else |
|
{ |
|
pEntity->CreateOnServer(); |
|
pEntity->MarkDirty(); |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Load the VMF file, merge in all the edits, write it back out |
|
//----------------------------------------------------------------------------- |
|
bool CVcdBlockDoc::CopyEditsToVMF( ) |
|
{ |
|
const CDmrElementArray<CDmElement> entityList = GetEntityList(); |
|
|
|
CDmElement *pVMF = NULL; |
|
DmFileId_t fileid = g_pDataModel->FindOrCreateFileId( m_pVMFFileName ); |
|
if ( g_pDataModel->RestoreFromFile( m_pVMFFileName, NULL, "vmf", &pVMF ) == DMFILEID_INVALID ) |
|
{ |
|
// needs some kind of error message |
|
return false; |
|
} |
|
|
|
CDmrElementArray<CDmElement> vmfEntities( pVMF, "entities" ); |
|
|
|
int nVMFCount = vmfEntities.Count(); |
|
for (int i = 0; i < nVMFCount; i++) |
|
{ |
|
CDmElement *pVMFEntity = vmfEntities[i]; |
|
|
|
char classname[256]; |
|
pVMFEntity->GetValueAsString( "classname", classname, sizeof( classname ) ); |
|
|
|
if ( Q_stricmp( "info_target", classname ) ) |
|
continue; |
|
|
|
int nHammerID = atoi( pVMFEntity->GetName() ); |
|
|
|
// find a match. |
|
int nCount = entityList.Count(); |
|
for (int j = 0; j < nCount; j++) |
|
{ |
|
CDmeVMFEntity *pEntity = CastElement<CDmeVMFEntity>( entityList[j] ); |
|
|
|
if ( pEntity->IsDirty() && pEntity->GetEntityId() == nHammerID) |
|
{ |
|
char text[256]; |
|
pEntity->GetValueAsString( "targetname", text, sizeof( text ) ); |
|
pVMFEntity->SetValueFromString( "targetname", text ); |
|
pEntity->GetValueAsString( "origin", text, sizeof( text ) ); |
|
pVMFEntity->SetValueFromString( "origin", text ); |
|
pEntity->GetValueAsString( "angles", text, sizeof( text ) ); |
|
pVMFEntity->SetValueFromString( "angles", text ); |
|
|
|
pEntity->MarkDirty(false); |
|
} |
|
} |
|
} |
|
|
|
// add the new entities |
|
int nCount = entityList.Count(); |
|
for (int j = 0; j < nCount; j++) |
|
{ |
|
CDmeVMFEntity *pEntity = CastElement<CDmeVMFEntity>( entityList[j] ); |
|
|
|
if ( pEntity->IsDirty()) |
|
{ |
|
CDmElement *pVMFEntity = CreateElement<CDmElement>( pEntity->GetName(), fileid ); |
|
|
|
char text[256]; |
|
pEntity->GetValueAsString( "classname", text, sizeof( text ) ); |
|
pVMFEntity->SetValue( "classname", text ); |
|
pEntity->GetValueAsString( "targetname", text, sizeof( text ) ); |
|
pVMFEntity->SetValue( "targetname", text ); |
|
pEntity->GetValueAsString( "origin", text, sizeof( text ) ); |
|
pVMFEntity->SetValue( "origin", text ); |
|
pEntity->GetValueAsString( "angles", text, sizeof( text ) ); |
|
pVMFEntity->SetValue( "angles", text ); |
|
|
|
vmfEntities.AddToTail( pVMFEntity ); |
|
|
|
pEntity->MarkDirty(false); |
|
} |
|
} |
|
|
|
// currently, don't overwrite the vmf, not sure if this is serializing correctly yet |
|
char tmpname[ 256 ]; |
|
Q_StripExtension( m_pVMFFileName, tmpname, sizeof(tmpname) ); |
|
Q_SetExtension( tmpname, ".vme", sizeof(tmpname) ); |
|
|
|
if (!g_pDataModel->SaveToFile( tmpname, NULL, "keyvalues", "vmf", pVMF )) |
|
{ |
|
// needs some kind of error message |
|
return false; |
|
} |
|
|
|
/* |
|
// If we successfully read the file in, ask it for the max hammer id |
|
int nMaxHammerId = pVMF->GetAttributeValue<int>( "maxHammerId" ); |
|
CDmeVMFEntity::SetNextEntityId( nMaxHammerId + 1 ); |
|
m_hVMFRoot = pVMF; |
|
*/ |
|
|
|
return true; |
|
} |
|
|
|
|
|
bool CVcdBlockDoc::RememberPlayerPosition() |
|
{ |
|
return true; |
|
}
|
|
|