311 lines
7.5 KiB
C++
311 lines
7.5 KiB
C++
|
//====== Copyright c 1996-2007, Valve Corporation, All rights reserved. =======//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include "platform.h"
|
||
|
#include "utlvector.h"
|
||
|
#include "utlbuffer.h"
|
||
|
#include "chunkfile.h"
|
||
|
#include "utlencode.h"
|
||
|
#include "fgdlib/wckeyvalues.h"
|
||
|
#include "vmfmeshdatasupport.h"
|
||
|
|
||
|
|
||
|
CVmfMeshDataSupport_SaveLoadHandler::CVmfMeshDataSupport_SaveLoadHandler()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CVmfMeshDataSupport_SaveLoadHandler::~CVmfMeshDataSupport_SaveLoadHandler()
|
||
|
{
|
||
|
NULL;
|
||
|
}
|
||
|
|
||
|
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::WriteDataChunk( CChunkFile *pFile, char const *szHash )
|
||
|
{
|
||
|
ChunkFileResult_t eResult;
|
||
|
eResult = pFile->BeginChunk( GetCustomSectionName() );
|
||
|
if ( eResult != ChunkFile_Ok )
|
||
|
return eResult;
|
||
|
|
||
|
// Write out our data version
|
||
|
char szModelDataVer[ 16 ] = {0};
|
||
|
sprintf( szModelDataVer, "%d", GetCustomSectionVer() );
|
||
|
eResult = pFile->WriteKeyValue( "version", szModelDataVer );
|
||
|
if ( eResult != ChunkFile_Ok )
|
||
|
return eResult;
|
||
|
|
||
|
// Write our hash
|
||
|
eResult = pFile->WriteKeyValue( "hash", szHash );
|
||
|
if ( eResult != ChunkFile_Ok )
|
||
|
return eResult;
|
||
|
|
||
|
// Write out additional data
|
||
|
eResult = OnFileDataWriting( pFile, szHash );
|
||
|
if ( eResult != ChunkFile_Ok )
|
||
|
return eResult;
|
||
|
|
||
|
return pFile->EndChunk();
|
||
|
}
|
||
|
|
||
|
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::OnFileDataWriting( CChunkFile *pFile, char const *szHash )
|
||
|
{
|
||
|
return ChunkFile_Ok;
|
||
|
}
|
||
|
|
||
|
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::WriteBufferData( CChunkFile *pFile, CUtlBuffer &bufData, char const *szPrefix )
|
||
|
{
|
||
|
int numEncBytes = KvEncoder::GuessEncodedLength( bufData.TellPut() );
|
||
|
CUtlBuffer bufEncoded;
|
||
|
bufEncoded.EnsureCapacity( numEncBytes );
|
||
|
|
||
|
if ( !KvEncoder::Encode( bufData, bufEncoded ) )
|
||
|
return ChunkFile_Fail;
|
||
|
numEncBytes = bufEncoded.TellPut();
|
||
|
|
||
|
// Now we have the encoded data, split it into blocks
|
||
|
int numBytesPerLine = KEYVALUE_MAX_VALUE_LENGTH - 2;
|
||
|
int numLines = (numEncBytes + numBytesPerLine - 1 ) / numBytesPerLine;
|
||
|
int numLastLineBytes = numEncBytes % numBytesPerLine;
|
||
|
if ( !numLastLineBytes )
|
||
|
numLastLineBytes = numBytesPerLine;
|
||
|
|
||
|
// Key buffer
|
||
|
char chKeyBuf[ KEYVALUE_MAX_KEY_LENGTH ] = {0};
|
||
|
char chKeyValue[ KEYVALUE_MAX_VALUE_LENGTH ] = {0};
|
||
|
|
||
|
// Write the data
|
||
|
ChunkFileResult_t eResult;
|
||
|
|
||
|
sprintf( chKeyBuf, "%s_ebytes", szPrefix );
|
||
|
eResult = pFile->WriteKeyValueInt( chKeyBuf, numEncBytes );
|
||
|
if ( eResult != ChunkFile_Ok )
|
||
|
return eResult;
|
||
|
|
||
|
sprintf( chKeyBuf, "%s_rbytes", szPrefix );
|
||
|
eResult = pFile->WriteKeyValueInt( chKeyBuf, bufData.TellPut() );
|
||
|
if ( eResult != ChunkFile_Ok )
|
||
|
return eResult;
|
||
|
|
||
|
sprintf( chKeyBuf, "%s_lines", szPrefix );
|
||
|
eResult = pFile->WriteKeyValueInt( chKeyBuf, numLines );
|
||
|
if ( eResult != ChunkFile_Ok )
|
||
|
return eResult;
|
||
|
|
||
|
for ( int ln = 0; ln < numLines; ++ ln )
|
||
|
{
|
||
|
int lnLen = ( ln < (numLines - 1) ) ? numBytesPerLine : numLastLineBytes;
|
||
|
|
||
|
sprintf( chKeyBuf, "%s_ln_%d", szPrefix, ln );
|
||
|
sprintf( chKeyValue, "%.*s", lnLen, ( char * ) bufEncoded.Base() + ln * numBytesPerLine );
|
||
|
|
||
|
eResult = pFile->WriteKeyValue( chKeyBuf, chKeyValue );
|
||
|
if ( eResult != ChunkFile_Ok )
|
||
|
return eResult;
|
||
|
}
|
||
|
|
||
|
return ChunkFile_Ok;
|
||
|
|
||
|
}
|
||
|
|
||
|
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadKeyValueBegin( CChunkFile *pFile )
|
||
|
{
|
||
|
m_eLoadState = LOAD_VERSION;
|
||
|
m_iLoadVer = 0;
|
||
|
m_hLoadHeader.sHash[0] = 0;
|
||
|
LoadInitHeader();
|
||
|
|
||
|
return ChunkFile_Ok;
|
||
|
}
|
||
|
|
||
|
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadKeyValue( const char *szKey, const char *szValue )
|
||
|
{
|
||
|
switch ( m_eLoadState )
|
||
|
{
|
||
|
case LOAD_VERSION:
|
||
|
return LoadKeyValue_Hdr( szKey, szValue );
|
||
|
|
||
|
default:
|
||
|
switch ( m_iLoadVer )
|
||
|
{
|
||
|
case 1:
|
||
|
return LoadKeyValue_Ver1( szKey, szValue );
|
||
|
default:
|
||
|
return ChunkFile_Fail;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadKeyValue_Hdr( const char *szKey, const char *szValue )
|
||
|
{
|
||
|
switch ( m_eLoadState )
|
||
|
{
|
||
|
case LOAD_VERSION:
|
||
|
if ( stricmp( szKey, "version" ) )
|
||
|
return ChunkFile_Fail;
|
||
|
m_iLoadVer = atoi( szValue );
|
||
|
|
||
|
switch ( m_iLoadVer )
|
||
|
{
|
||
|
case 1:
|
||
|
m_eLoadState = LOAD_HASH;
|
||
|
return ChunkFile_Ok;
|
||
|
default:
|
||
|
return ChunkFile_Fail;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
return ChunkFile_Fail;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadKeyValue_Ver1( const char *szKey, const char *szValue )
|
||
|
{
|
||
|
const char *szKeyName = szKey;
|
||
|
const int nPrefixLen = 3;
|
||
|
|
||
|
switch ( m_eLoadState )
|
||
|
{
|
||
|
case LOAD_HASH:
|
||
|
if ( stricmp( szKey, "hash" ) )
|
||
|
return ChunkFile_Fail;
|
||
|
strncpy( m_hLoadHeader.sHash, szValue, sizeof( m_hLoadHeader.sHash ) );
|
||
|
m_eLoadState = LOAD_PREFIX;
|
||
|
break;
|
||
|
|
||
|
case LOAD_PREFIX:
|
||
|
sprintf( m_hLoadHeader.sPrefix, "%.*s", nPrefixLen, szKey );
|
||
|
if ( strlen( szKey ) < 4 )
|
||
|
return ChunkFile_Fail;
|
||
|
if ( szKey[3] != '_' )
|
||
|
return ChunkFile_Fail;
|
||
|
m_eLoadState = LOAD_HEADER;
|
||
|
// fall-through
|
||
|
|
||
|
case LOAD_HEADER:
|
||
|
if ( strnicmp( m_hLoadHeader.sPrefix, szKey, nPrefixLen ) )
|
||
|
return ChunkFile_Fail;
|
||
|
if ( szKey[3] != '_' )
|
||
|
return ChunkFile_Fail;
|
||
|
|
||
|
szKeyName = szKey + 4;
|
||
|
if ( !stricmp( szKeyName, "ebytes" ) )
|
||
|
m_hLoadHeader.numEncBytes = atoi( szValue );
|
||
|
else if ( !stricmp( szKeyName, "rbytes" ) )
|
||
|
m_hLoadHeader.numBytes = atoi( szValue );
|
||
|
else if ( !stricmp( szKeyName, "lines" ) )
|
||
|
m_hLoadHeader.numLines = atoi( szValue );
|
||
|
else
|
||
|
return ChunkFile_Fail;
|
||
|
|
||
|
if ( !LoadHaveHeader() )
|
||
|
break;
|
||
|
|
||
|
m_eLoadState = LOAD_DATA;
|
||
|
return LoadHaveLines( 0 );
|
||
|
|
||
|
case LOAD_DATA:
|
||
|
if ( strnicmp( m_hLoadHeader.sPrefix, szKey, nPrefixLen ) )
|
||
|
return ChunkFile_Fail;
|
||
|
if ( szKey[3] != '_' )
|
||
|
return ChunkFile_Fail;
|
||
|
|
||
|
szKeyName = szKey + 4;
|
||
|
if ( strnicmp( szKeyName, "ln", 2 ) || szKeyName[2] != '_' )
|
||
|
return ChunkFile_Fail;
|
||
|
|
||
|
szKeyName += 3;
|
||
|
{
|
||
|
int iLineNum = atoi( szKeyName );
|
||
|
if ( iLineNum != m_hLoadHeader.numHaveLines )
|
||
|
return ChunkFile_Fail;
|
||
|
|
||
|
m_bufLoadData.Put( szValue, strlen( szValue ) );
|
||
|
|
||
|
return LoadHaveLines( iLineNum + 1 );
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
return ChunkFile_Fail;
|
||
|
}
|
||
|
|
||
|
return ChunkFile_Ok;
|
||
|
}
|
||
|
|
||
|
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadKeyValueEnd( CChunkFile *pFile, ChunkFileResult_t eLoadResult )
|
||
|
{
|
||
|
if ( eLoadResult != ChunkFile_Ok )
|
||
|
return eLoadResult;
|
||
|
|
||
|
if ( m_eLoadState == LOAD_VERSION )
|
||
|
return ChunkFile_Ok;
|
||
|
|
||
|
switch ( m_iLoadVer )
|
||
|
{
|
||
|
case 1:
|
||
|
switch ( m_eLoadState )
|
||
|
{
|
||
|
case LOAD_HASH:
|
||
|
case LOAD_PREFIX:
|
||
|
return ChunkFile_Ok;
|
||
|
|
||
|
default:
|
||
|
return ChunkFile_Fail;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
return ChunkFile_Fail;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CVmfMeshDataSupport_SaveLoadHandler::LoadInitHeader()
|
||
|
{
|
||
|
m_hLoadHeader.sPrefix[0] = 0;
|
||
|
m_hLoadHeader.numLines = -1;
|
||
|
m_hLoadHeader.numBytes = -1;
|
||
|
m_hLoadHeader.numEncBytes = -1;
|
||
|
m_hLoadHeader.numHaveLines = 0;
|
||
|
}
|
||
|
|
||
|
bool CVmfMeshDataSupport_SaveLoadHandler::LoadHaveHeader()
|
||
|
{
|
||
|
return m_hLoadHeader.numLines >= 0 && m_hLoadHeader.numBytes >= 0 && m_hLoadHeader.numEncBytes >= 0;
|
||
|
}
|
||
|
|
||
|
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadHaveLines( int numHaveLines )
|
||
|
{
|
||
|
if ( !numHaveLines )
|
||
|
{
|
||
|
m_bufLoadData.EnsureCapacity( m_hLoadHeader.numEncBytes );
|
||
|
m_bufLoadData.SeekPut( CUtlBuffer::SEEK_HEAD, 0 );
|
||
|
}
|
||
|
|
||
|
m_hLoadHeader.numHaveLines = numHaveLines;
|
||
|
if ( m_hLoadHeader.numHaveLines < m_hLoadHeader.numLines )
|
||
|
return ChunkFile_Ok;
|
||
|
if ( m_hLoadHeader.numHaveLines > m_hLoadHeader.numLines )
|
||
|
return ChunkFile_Fail;
|
||
|
|
||
|
ChunkFileResult_t eRes = LoadSaveFullData();
|
||
|
if ( eRes != ChunkFile_Ok )
|
||
|
return eRes;
|
||
|
|
||
|
LoadInitHeader();
|
||
|
m_eLoadState = LOAD_PREFIX;
|
||
|
return ChunkFile_Ok;
|
||
|
}
|
||
|
|
||
|
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadSaveFullData()
|
||
|
{
|
||
|
// The filename
|
||
|
CUtlBuffer bufBytes;
|
||
|
bufBytes.EnsureCapacity( m_hLoadHeader.numBytes + 0x10 );
|
||
|
if ( !KvEncoder::Decode( m_bufLoadData, bufBytes ) )
|
||
|
return ChunkFile_Fail;
|
||
|
|
||
|
return OnFileDataLoaded( bufBytes );
|
||
|
}
|