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.
629 lines
19 KiB
629 lines
19 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//============================================================================= |
|
|
|
#include "importkeyvaluebase.h" |
|
#include "dmserializers.h" |
|
#include "datamodel/idatamodel.h" |
|
#include "datamodel/dmelement.h" |
|
#include "tier1/KeyValues.h" |
|
#include "tier1/utlbuffer.h" |
|
#include "datamodel/dmattribute.h" |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Serialization class for VMF files (map files) |
|
//----------------------------------------------------------------------------- |
|
class CImportVMF : public CImportKeyValueBase |
|
{ |
|
public: |
|
virtual const char *GetName() const { return "vmf"; } |
|
virtual const char *GetDescription() const { return "Valve Map File"; } |
|
virtual int GetCurrentVersion() const { return 0; } // doesn't store a version |
|
|
|
bool Serialize( CUtlBuffer &outBuf, CDmElement *pRoot ); |
|
CDmElement* UnserializeFromKeyValues( KeyValues *pKeyValues ); |
|
|
|
private: |
|
// Reads a single entity |
|
bool UnserializeEntityKey( CDmAttribute *pEntities, KeyValues *pKeyValues ); |
|
|
|
// Reads entity editor keys |
|
bool UnserializeEntityEditorKey( CDmAttribute *pEditor, KeyValues *pKeyValues ); |
|
|
|
// Reads keys that we currently do nothing with |
|
bool UnserializeUnusedKeys( DmElementHandle_t hOther, KeyValues *pKeyValues ); |
|
|
|
// Writes out all everything other than entities |
|
bool SerializeOther( CUtlBuffer &buf, CDmAttribute *pOther, const char **ppFilter = 0 ); |
|
|
|
// Writes out all entities |
|
bool SerializeEntities( CUtlBuffer &buf, CDmAttribute *pEntities ); |
|
|
|
// Writes out a single attribute recursively |
|
bool SerializeAttribute( CUtlBuffer &buf, CDmAttribute *pAttribute, bool bElementArrays ); |
|
|
|
// Writes entity editor keys |
|
bool SerializeEntityEditorKey( CUtlBuffer &buf, DmElementHandle_t hEditor ); |
|
|
|
// Updates the max hammer id |
|
void UpdateMaxHammerId( KeyValues *pKeyValue ); |
|
|
|
// Max id read from the file |
|
int m_nMaxHammerId; |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Singleton instance |
|
//----------------------------------------------------------------------------- |
|
static CImportVMF s_ImportVMF; |
|
|
|
void InstallVMFImporter( IDataModel *pFactory ) |
|
{ |
|
pFactory->AddSerializer( &s_ImportVMF ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Deals with poorly-named key values for the DME system |
|
//----------------------------------------------------------------------------- |
|
static const char *s_pKeyRemapNames[][2] = |
|
{ |
|
{ "id", "__id" }, |
|
{ "name", "__name" }, |
|
{ "type", "__type" }, |
|
{ NULL, NULL }, |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Gets remap name for unserialization/serailzation |
|
//----------------------------------------------------------------------------- |
|
static const char *GetRemapName( const char *pName, bool bSerialization ) |
|
{ |
|
for ( int i = 0; s_pKeyRemapNames[i][0]; ++i ) |
|
{ |
|
if ( !Q_stricmp( pName, s_pKeyRemapNames[i][bSerialization] ) ) |
|
return s_pKeyRemapNames[i][1 - bSerialization]; |
|
} |
|
return pName; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Writes out a single attribute recursively |
|
//----------------------------------------------------------------------------- |
|
bool CImportVMF::SerializeAttribute( CUtlBuffer &buf, CDmAttribute *pAttribute, bool bElementArrays ) |
|
{ |
|
if ( pAttribute->IsFlagSet( FATTRIB_STANDARD | FATTRIB_DONTSAVE ) ) |
|
return true; |
|
|
|
const char *pFieldName = GetRemapName( pAttribute->GetName(), true ); |
|
if ( !Q_stricmp( pFieldName, "editorType" ) ) |
|
return true; |
|
|
|
if ( !IsArrayType( pAttribute->GetType() ) ) |
|
{ |
|
if ( !bElementArrays ) |
|
{ |
|
buf.Printf( "\"%s\" ", pFieldName ); |
|
if ( pAttribute->GetType() != AT_STRING ) |
|
{ |
|
buf.Printf( "\"" ); |
|
} |
|
g_pDataModel->SetSerializationDelimiter( GetCStringCharConversion() ); |
|
pAttribute->Serialize( buf ); |
|
g_pDataModel->SetSerializationDelimiter( NULL ); |
|
if ( pAttribute->GetType() != AT_STRING ) |
|
{ |
|
buf.Printf( "\"" ); |
|
} |
|
buf.Printf( "\n" ); |
|
} |
|
} |
|
else |
|
{ |
|
if ( bElementArrays ) |
|
{ |
|
Assert( pAttribute->GetType() == AT_ELEMENT_ARRAY ); |
|
if ( !SerializeOther( buf, pAttribute ) ) |
|
return false; |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Writes out all everything other than entities |
|
//----------------------------------------------------------------------------- |
|
bool CImportVMF::SerializeOther( CUtlBuffer &buf, CDmAttribute *pOther, const char **ppFilter ) |
|
{ |
|
CDmrElementArray<> array( pOther ); |
|
int nCount = array.Count(); |
|
for ( int i = 0; i < nCount; ++i ) |
|
{ |
|
CDmElement *pElement = array[i]; |
|
const char *pElementName = pElement->GetName(); |
|
if ( ppFilter ) |
|
{ |
|
int j; |
|
for ( j = 0; ppFilter[j]; ++j ) |
|
{ |
|
if ( !Q_stricmp( pElementName, ppFilter[j] ) ) |
|
break; |
|
} |
|
|
|
if ( !ppFilter[j] ) |
|
continue; |
|
} |
|
|
|
int nLen = Q_strlen( pElementName ) + 1; |
|
char *pTemp = (char*)_alloca( nLen ); |
|
Q_strncpy( pTemp, pElementName, nLen ); |
|
Q_strlower( pTemp ); |
|
buf.Printf( "%s\n", pTemp ); |
|
buf.Printf( "{\n" ); |
|
buf.PushTab(); |
|
|
|
// Normal attributes first |
|
for( CDmAttribute *pAttribute = pElement->FirstAttribute(); pAttribute; pAttribute = pAttribute->NextAttribute() ) |
|
{ |
|
if ( !SerializeAttribute( buf, pAttribute, false ) ) |
|
return false; |
|
} |
|
|
|
// Subkeys later |
|
for( CDmAttribute *pAttribute = pElement->FirstAttribute(); pAttribute; pAttribute = pAttribute->NextAttribute() ) |
|
{ |
|
if ( !SerializeAttribute( buf, pAttribute, true ) ) |
|
return false; |
|
} |
|
|
|
buf.PopTab(); |
|
buf.Printf( "}\n" ); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Writes entity editor keys |
|
//----------------------------------------------------------------------------- |
|
bool CImportVMF::SerializeEntityEditorKey( CUtlBuffer &buf, DmElementHandle_t hEditor ) |
|
{ |
|
CDmElement *pEditorElement = g_pDataModel->GetElement( hEditor ); |
|
if ( !pEditorElement ) |
|
return true; |
|
|
|
buf.Printf( "editor\n" ); |
|
buf.Printf( "{\n" ); |
|
buf.PushTab(); |
|
|
|
{ |
|
CDmAttribute *pAttribute = pEditorElement->GetAttribute( "color" ); |
|
if ( pAttribute ) |
|
{ |
|
Color c = pAttribute->GetValue<Color>(); |
|
buf.Printf( "\"color\" \"%d %d %d\"\n", c.r(), c.g(), c.b() ); |
|
} |
|
} |
|
PrintIntAttribute( pEditorElement, buf, "id" ); // FIXME - id is a DmObjectId_t!!! This should never print anything! |
|
PrintStringAttribute( pEditorElement, buf, "comments" ); |
|
PrintBoolAttribute( pEditorElement, buf, "visgroupshown" ); |
|
PrintBoolAttribute( pEditorElement, buf, "visgroupautoshown" ); |
|
|
|
for ( CDmAttribute *pAttribute = pEditorElement->FirstAttribute(); pAttribute != NULL; pAttribute = pAttribute->NextAttribute() ) |
|
{ |
|
if ( pAttribute->IsFlagSet( FATTRIB_STANDARD | FATTRIB_DONTSAVE ) ) |
|
continue; |
|
|
|
const char *pKeyName = pAttribute->GetName(); |
|
if ( Q_stricmp( pKeyName, "color" ) && Q_stricmp( pKeyName, "id" ) && |
|
Q_stricmp( pKeyName, "comments" ) && Q_stricmp( pKeyName, "visgroupshown" ) && |
|
Q_stricmp( pKeyName, "visgroupautoshown" ) ) |
|
{ |
|
PrintStringAttribute( pEditorElement, buf, pKeyName ); |
|
} |
|
} |
|
|
|
buf.PopTab(); |
|
buf.Printf( "}\n" ); |
|
|
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Writes out all entities |
|
//----------------------------------------------------------------------------- |
|
bool CImportVMF::SerializeEntities( CUtlBuffer &buf, CDmAttribute *pEntities ) |
|
{ |
|
// FIXME: Make this serialize in the order in which it appears in the FGD |
|
// to minimize diffs |
|
CDmrElementArray<> array( pEntities ); |
|
|
|
int nCount = array.Count(); |
|
for ( int i = 0; i < nCount; ++i ) |
|
{ |
|
CDmElement *pElement = array[i]; |
|
buf.Printf( "entity\n" ); |
|
buf.Printf( "{\n" ); |
|
buf.PushTab(); |
|
buf.Printf( "\"id\" \"%s\"\n", pElement->GetName() ); |
|
|
|
for( CDmAttribute *pAttribute = pElement->FirstAttribute(); pAttribute; pAttribute = pAttribute->NextAttribute() ) |
|
{ |
|
// Do 'editor' at the end to preserve ordering and not make terrible diffs |
|
if ( !Q_stricmp( pAttribute->GetName(), "editor" ) ) |
|
continue; |
|
|
|
if ( !SerializeAttribute( buf, pAttribute, false ) ) |
|
return false; |
|
} |
|
|
|
for( CDmAttribute *pAttribute = pElement->FirstAttribute(); pAttribute; pAttribute = pAttribute->NextAttribute() ) |
|
{ |
|
// Do 'editor' at the end to preserve ordering and not make terrible diffs |
|
if ( !Q_stricmp( pAttribute->GetName(), "editor" ) ) |
|
continue; |
|
|
|
if ( !SerializeAttribute( buf, pAttribute, true ) ) |
|
return false; |
|
} |
|
|
|
// Do the 'editor' |
|
CDmAttribute *pEditor = pElement->GetAttribute( "editor" ); |
|
if ( pEditor ) |
|
{ |
|
SerializeEntityEditorKey( buf, pEditor->GetValue<DmElementHandle_t>() ); |
|
} |
|
|
|
buf.PopTab(); |
|
buf.Printf( "}\n" ); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Writes out a new VMF file |
|
//----------------------------------------------------------------------------- |
|
bool CImportVMF::Serialize( CUtlBuffer &buf, CDmElement *pRoot ) |
|
{ |
|
// This is done in this strange way (namely, serializing other twice) to minimize diffs |
|
const char *pOtherFilter1[] = |
|
{ |
|
"versioninfo", "visgroups", "viewsettings", "world", NULL |
|
}; |
|
|
|
const char *pOtherFilter2[] = |
|
{ |
|
"cameras", "cordon", "hidden", NULL |
|
}; |
|
|
|
CDmAttribute *pOther = pRoot->GetAttribute( "other" ); |
|
if ( pOther && pOther->GetType() == AT_ELEMENT_ARRAY ) |
|
{ |
|
if ( !SerializeOther( buf, pOther, pOtherFilter1 ) ) |
|
return false; |
|
} |
|
|
|
// Serialize entities |
|
CDmAttribute *pEntities = pRoot->GetAttribute( "entities" ); |
|
if ( pEntities && pEntities->GetType() == AT_ELEMENT_ARRAY ) |
|
{ |
|
if ( !SerializeEntities( buf, pEntities ) ) |
|
return false; |
|
} |
|
|
|
if ( pOther && pOther->GetType() == AT_ELEMENT_ARRAY ) |
|
{ |
|
if ( !SerializeOther( buf, pOther, pOtherFilter2 ) ) |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Updates the max hammer id |
|
//----------------------------------------------------------------------------- |
|
void CImportVMF::UpdateMaxHammerId( KeyValues *pField ) |
|
{ |
|
if ( !Q_stricmp( pField->GetName(), "id" ) ) |
|
{ |
|
int nId = atoi( pField->GetString() ); |
|
if ( nId > m_nMaxHammerId ) |
|
{ |
|
m_nMaxHammerId = nId; |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Reads entity editor keys |
|
//----------------------------------------------------------------------------- |
|
bool CImportVMF::UnserializeEntityEditorKey( CDmAttribute *pEditorAttribute, KeyValues *pKeyValues ) |
|
{ |
|
CDmElement *pEditor; |
|
DmElementHandle_t hEditor = pEditorAttribute->GetValue<DmElementHandle_t>(); |
|
if ( hEditor == DMELEMENT_HANDLE_INVALID ) |
|
{ |
|
pEditor = CreateDmElement( "DmElement", "editor", NULL );; |
|
if ( !pEditor ) |
|
return false; |
|
hEditor = pEditor->GetHandle(); |
|
pEditorAttribute->SetValue( hEditor ); |
|
} |
|
else |
|
{ |
|
pEditor = g_pDataModel->GetElement( hEditor ); |
|
} |
|
|
|
int r, g, b; |
|
if ( sscanf( pKeyValues->GetString( "color", "" ), "%d %d %d", &r, &g, &b ) == 3 ) |
|
{ |
|
Color c( r, g, b, 255 ); |
|
if ( !pEditor->SetValue( "color", c ) ) |
|
return false; |
|
} |
|
KeyValues *pIdKey = pKeyValues->FindKey( "id" ); |
|
if ( pIdKey ) |
|
{ |
|
UpdateMaxHammerId( pIdKey ); |
|
} |
|
AddIntAttribute( pEditor, pKeyValues, "id" ); |
|
AddStringAttribute( pEditor, pKeyValues, "comments" ); |
|
AddBoolAttribute( pEditor, pKeyValues, "visgroupshown" ); |
|
AddBoolAttribute( pEditor, pKeyValues, "visgroupautoshown" ); |
|
|
|
for ( KeyValues *pUserKey = pKeyValues->GetFirstValue(); pUserKey != NULL; pUserKey = pUserKey->GetNextValue() ) |
|
{ |
|
const char *pKeyName = pUserKey->GetName(); |
|
if ( Q_stricmp( pKeyName, "color" ) && Q_stricmp( pKeyName, "id" ) && |
|
Q_stricmp( pKeyName, "comments" ) && Q_stricmp( pKeyName, "visgroupshown" ) && |
|
Q_stricmp( pKeyName, "visgroupautoshown" ) ) |
|
{ |
|
AddStringAttribute( pEditor, pKeyValues, pKeyName ); |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Reads a single entity |
|
//----------------------------------------------------------------------------- |
|
bool CImportVMF::UnserializeEntityKey( CDmAttribute *pEntities, KeyValues *pKeyValues ) |
|
{ |
|
CDmElement *pEntity = CreateDmElement( "DmeVMFEntity", pKeyValues->GetString( "id", "-1" ), NULL ); |
|
if ( !pEntity ) |
|
return false; |
|
|
|
CDmrElementArray<> array( pEntities ); |
|
array.AddToTail( pEntity ); |
|
|
|
// Each act busy needs to have an editortype associated with it so it displays nicely in editors |
|
pEntity->SetValue( "editorType", "vmfEntity" ); |
|
|
|
const char *pClassName = pKeyValues->GetString( "classname", NULL ); |
|
if ( !pClassName ) |
|
return false; |
|
|
|
// Read the actual fields |
|
for ( KeyValues *pField = pKeyValues->GetFirstValue(); pField != NULL; pField = pField->GetNextValue() ) |
|
{ |
|
// FIXME: Knowing the FGD here would be useful for type determination. |
|
// Look up the field by name based on class name |
|
// In the meantime, just use the keyvalues type? |
|
char pFieldName[512]; |
|
Q_strncpy( pFieldName, pField->GetName(), sizeof(pFieldName) ); |
|
Q_strlower( pFieldName ); |
|
|
|
// Don't do id: it's used as the name |
|
// Not to mention it's a protected name |
|
if ( !Q_stricmp( pFieldName, "id" ) ) |
|
{ |
|
UpdateMaxHammerId( pField ); |
|
continue; |
|
} |
|
|
|
// Type, name, and editortype are protected names |
|
Assert( Q_stricmp( pFieldName, "type" ) && Q_stricmp( pFieldName, "name" ) && Q_stricmp( pFieldName, "editortype" ) ); |
|
|
|
switch( pField->GetDataType() ) |
|
{ |
|
case KeyValues::TYPE_INT: |
|
if ( !AddIntAttributeFlags( pEntity, pKeyValues, pFieldName, FATTRIB_USERDEFINED ) ) |
|
return false; |
|
break; |
|
|
|
case KeyValues::TYPE_FLOAT: |
|
if ( !AddFloatAttributeFlags( pEntity, pKeyValues, pFieldName, FATTRIB_USERDEFINED ) ) |
|
return false; |
|
break; |
|
|
|
case KeyValues::TYPE_STRING: |
|
{ |
|
const char* pString = pField->GetString(); |
|
if (!pString || !pString[0]) |
|
return false; |
|
|
|
// Look for vectors |
|
Vector4D v; |
|
if ( sscanf( pString, "%f %f %f %f", &v.x, &v.y, &v.z, &v.w ) == 4 ) |
|
{ |
|
if ( !pEntity->SetValue( pFieldName, v ) ) |
|
return false; |
|
CDmAttribute *pAttribute = pEntity->GetAttribute( pFieldName ); |
|
pAttribute->AddFlag( FATTRIB_USERDEFINED ); |
|
} |
|
else if ( sscanf( pString, "%f %f %f", &v.x, &v.y, &v.z ) == 3 ) |
|
{ |
|
if ( !pEntity->SetValue( pFieldName, v.AsVector3D() ) ) |
|
{ |
|
QAngle ang( v.x, v.y, v.z ); |
|
if ( !pEntity->SetValue( pFieldName, ang ) ) |
|
return false; |
|
} |
|
CDmAttribute *pAttribute = pEntity->GetAttribute( pFieldName ); |
|
pAttribute->AddFlag( FATTRIB_USERDEFINED ); |
|
} |
|
else |
|
{ |
|
if ( !AddStringAttributeFlags( pEntity, pKeyValues, pFieldName, FATTRIB_USERDEFINED ) ) |
|
return false; |
|
} |
|
} |
|
break; |
|
} |
|
} |
|
|
|
// Read the subkeys |
|
CDmAttribute *pEditor = pEntity->AddAttribute( "editor", AT_ELEMENT ); |
|
CDmrElementArray<> otherKeys( pEntity->AddAttribute( "other", AT_ELEMENT_ARRAY ) ); |
|
for ( KeyValues *pSubKey = pKeyValues->GetFirstTrueSubKey(); pSubKey != NULL; pSubKey = pSubKey->GetNextTrueSubKey() ) |
|
{ |
|
bool bOk = false; |
|
if ( !Q_stricmp( pSubKey->GetName(), "editor" ) ) |
|
{ |
|
bOk = UnserializeEntityEditorKey( pEditor, pSubKey ); |
|
} |
|
else |
|
{ |
|
// We don't currently do anything with the other keys |
|
CDmElement *pOther = CreateDmElement( "DmElement", pSubKey->GetName(), NULL ); |
|
otherKeys.AddToTail( pOther ); |
|
bOk = UnserializeUnusedKeys( pOther->GetHandle(), pSubKey ); |
|
} |
|
|
|
if ( !bOk ) |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Reads keys that we currently do nothing with |
|
//----------------------------------------------------------------------------- |
|
bool CImportVMF::UnserializeUnusedKeys( DmElementHandle_t hOther, KeyValues *pKeyValues ) |
|
{ |
|
CDmElement *pOther = g_pDataModel->GetElement( hOther ); |
|
|
|
// Read the actual fields |
|
for ( KeyValues *pField = pKeyValues->GetFirstValue(); pField != NULL; pField = pField->GetNextValue() ) |
|
{ |
|
UpdateMaxHammerId( pField ); |
|
const char *pFieldName = GetRemapName( pField->GetName(), false ); |
|
pOther->SetValue( pFieldName, pField->GetString() ); |
|
} |
|
|
|
// Read the subkeys |
|
CDmrElementArray<> subKeys( pOther->AddAttribute( "subkeys", AT_ELEMENT_ARRAY ) ); |
|
for ( KeyValues *pSubKey = pKeyValues->GetFirstTrueSubKey(); pSubKey != NULL; pSubKey = pSubKey->GetNextTrueSubKey() ) |
|
{ |
|
CDmElement *pSubElement = CreateDmElement( "DmElement", pSubKey->GetName(), NULL ); |
|
subKeys.AddToTail( pSubElement ); |
|
if ( !UnserializeUnusedKeys( pSubElement->GetHandle(), pSubKey ) ) |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
|
|
/* |
|
//----------------------------------------------------------------------------- |
|
// Reads the cordon data |
|
//----------------------------------------------------------------------------- |
|
bool CImportVMF::UnserializeCordonKey( IDmAttributeElement *pCordon, KeyValues *pKeyValues ) |
|
{ |
|
DmElementHandle_t hCordon = pCordon->GetValue().Get(); |
|
if ( hCordon == DMELEMENT_HANDLE_INVALID ) |
|
{ |
|
hCordon = CreateDmElement( "DmElement", "cordon", NULL ); |
|
if ( hCordon == DMELEMENT_HANDLE_INVALID ) |
|
return false; |
|
pCordon->SetValue( hCordon ); |
|
} |
|
|
|
AddBoolAttribute( hCordon, pKeyValues, "active" ); |
|
|
|
Vector v; |
|
if ( sscanf( pKeyValues->GetString( "mins", "" ), "(%f %f %f)", &v.x, &v.y, &v.z ) == 3 ) |
|
{ |
|
if ( !DmElementAddAttribute( hCordon, "mins", v ) ) |
|
return false; |
|
} |
|
if ( sscanf( pKeyValues->GetString( "maxs", "" ), "(%f %f %f)", &v.x, &v.y, &v.z ) == 3 ) |
|
{ |
|
if ( !DmElementAddAttribute( hCordon, "maxs", v ) ) |
|
return false; |
|
} |
|
return true; |
|
} |
|
*/ |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Main entry point for the unserialization |
|
//----------------------------------------------------------------------------- |
|
CDmElement* CImportVMF::UnserializeFromKeyValues( KeyValues *pKeyValues ) |
|
{ |
|
m_nMaxHammerId = 0; |
|
|
|
// Create the main element |
|
CDmElement *pElement = CreateDmElement( "DmElement", "VMF", NULL ); |
|
if ( !pElement ) |
|
return NULL; |
|
|
|
// Each vmf needs to have an editortype associated with it so it displays nicely in editors |
|
pElement->SetValue( "editorType", "VMF" ); |
|
|
|
// The VMF is a series of keyvalue blocks; either |
|
// 'entity', 'cameras', 'cordon', 'world', 'versioninfo', or 'viewsettings' |
|
CDmAttribute *pEntityArray = pElement->AddAttribute( "entities", AT_ELEMENT_ARRAY ); |
|
|
|
// All main keys are root keys |
|
CDmrElementArray<> otherKeys( pElement->AddAttribute( "other", AT_ELEMENT_ARRAY ) ); |
|
for ( ; pKeyValues != NULL; pKeyValues = pKeyValues->GetNextKey() ) |
|
{ |
|
bool bOk = false; |
|
if ( !Q_stricmp( pKeyValues->GetName(), "entity" ) ) |
|
{ |
|
bOk = UnserializeEntityKey( pEntityArray, pKeyValues ); |
|
} |
|
else |
|
{ |
|
// We don't currently do anything with |
|
CDmElement *pOther = CreateDmElement( "DmElement", pKeyValues->GetName(), NULL ); |
|
otherKeys.AddToTail( pOther ); |
|
bOk = UnserializeUnusedKeys( pOther->GetHandle(), pKeyValues ); |
|
} |
|
|
|
if ( !bOk ) |
|
{ |
|
Warning( "Error importing VMF element %s\n", pKeyValues->GetName() ); |
|
return NULL; |
|
} |
|
} |
|
|
|
// Resolve all element references recursively |
|
RecursivelyResolveElement( pElement ); |
|
|
|
// Add the max id read in from the file to the root entity |
|
pElement->SetValue( "maxHammerId", m_nMaxHammerId ); |
|
|
|
return pElement; |
|
}
|
|
|