source-engine-2018-hl2_src/dmserializers/importsfmv1.cpp

220 lines
7.4 KiB
C++
Raw Normal View History

2020-04-23 00:56:21 +08:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "dmserializers.h"
#include "dmebaseimporter.h"
#include "datamodel/idatamodel.h"
#include "datamodel/dmattribute.h"
#include "datamodel/dmelement.h"
#include <math.h>
//-----------------------------------------------------------------------------
// Format converter
//-----------------------------------------------------------------------------
class CImportSFMV1 : public CSFMBaseImporter
{
typedef CSFMBaseImporter BaseClass;
public:
CImportSFMV1( char const *formatName, char const *nextFormatName );
private:
virtual bool DoFixup( CDmElement *pSourceRoot );
// Fixes up a single time attribute - converting from float seconds to int tenths-of-a-millisecond
void ConvertTimeAttribute( CDmElement *pElementInternal, const char *pOldName, const char *pNewName );
// Fixes up a single timeframe
void FixupTimeframe( CDmElement *pElementInternal );
// Fixes up a single log - converting from int milliseconds to int tenths-of-a-millisecond
void FixupLog( CDmElement *pElementInternal );
CUtlRBTree< CDmElement*, int > m_fixedElements;
};
//-----------------------------------------------------------------------------
// Singleton instance
//-----------------------------------------------------------------------------
static CImportSFMV1 s_ImportDmxV1( "sfm_v1", "sfm_v2" );
void InstallSFMV1Importer( IDataModel *pFactory )
{
pFactory->AddLegacyUpdater( &s_ImportDmxV1 );
}
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CImportSFMV1::CImportSFMV1( char const *formatName, char const *nextFormatName ) :
BaseClass( formatName, nextFormatName )
{
m_fixedElements.SetLessFunc( DefLessFunc( CDmElement * ) );
}
//-----------------------------------------------------------------------------
// Fixes up all elements
//-----------------------------------------------------------------------------
bool CImportSFMV1::DoFixup( CDmElement *pElementInternal )
{
if ( !pElementInternal )
return true;
if ( m_fixedElements.Find( pElementInternal ) != m_fixedElements.InvalidIndex() )
return true;
m_fixedElements.Insert( pElementInternal );
const char *pType = pElementInternal->GetTypeString();
if ( !Q_strcmp( pType, "DmeTimeFrame" ) )
{
FixupTimeframe( pElementInternal );
}
else if ( !Q_strcmp( pType, "DmeLog" ) ||
!Q_strcmp( pType, "DmeIntLog" ) ||
!Q_strcmp( pType, "DmeFloatLog" ) ||
!Q_strcmp( pType, "DmeBoolLog" ) ||
!Q_strcmp( pType, "DmeColorLog" ) ||
!Q_strcmp( pType, "DmeVector2Log" ) ||
!Q_strcmp( pType, "DmeVector3Log" ) ||
!Q_strcmp( pType, "DmeVector4Log" ) ||
!Q_strcmp( pType, "DmeQAngleLog" ) ||
!Q_strcmp( pType, "DmeQuaternionLog" ) ||
!Q_strcmp( pType, "DmeVMatrixLog" ) )
{
FixupLog( pElementInternal );
}
for ( CDmAttribute *pAttribute = pElementInternal->FirstAttribute(); pAttribute; pAttribute = pAttribute->NextAttribute() )
{
if ( pAttribute->GetType() == AT_ELEMENT )
{
CDmElement *pElement = pAttribute->GetValueElement<CDmElement>( );
DoFixup( pElement );
continue;
}
if ( pAttribute->GetType() == AT_ELEMENT_ARRAY )
{
CDmrElementArray<> array( pAttribute );
int nCount = array.Count();
for ( int i = 0; i < nCount; ++i )
{
CDmElement *pChild = array[ i ];
DoFixup( pChild );
}
continue;
}
}
return true;
}
//-----------------------------------------------------------------------------
// Fixes up a single time attribute - converting from float seconds to int tenths-of-a-millisecond
//-----------------------------------------------------------------------------
void CImportSFMV1::ConvertTimeAttribute( CDmElement *pElementInternal, const char *pOldName, const char *pNewName )
{
float time = 0.0f;
CDmAttribute *pOldAttr = pElementInternal->GetAttribute( pOldName );
if ( !pOldAttr )
{
Warning( "*** Problem in file encountered!\n" );
Warning( "*** TimeFrame \"%s\" is missing attribute \"%s\"!\n", pElementInternal->GetName(), pOldName );
Warning( "*** Setting new attribute \"%s\" to 0\n", pNewName );
}
else if ( pOldAttr->GetType() != AT_FLOAT )
{
Warning( "*** Problem in file encountered!\n" );
Warning( "*** TimeFrame \"%s\" has attribute \"%s\" with an unexpected type (expected float)!\n", pElementInternal->GetName(), pOldName );
}
else
{
time = pOldAttr->GetValue< float >();
pElementInternal->RemoveAttribute( pOldName );
}
CDmAttribute *pNewAttr = NULL;
// this is disabled because even dmxconvert installs *some* movieobjects factories, when it probably shouldn't
// the method of installing movieobjects factories will change at some point in the future, and we can turn on this safety check then
#if 0
int i = g_pDataModel->GetFirstFactory();
if ( g_pDataModel->IsValidFactory( i ) )
{
// factories installed - most likely from within movieobjects.lib
// ie there may be different ways of allocating attributes, so it's not safe to add them here
pNewAttr = pElementInternal->GetAttribute( pNewName );
if ( !pNewAttr || pNewAttr->GetType() != AT_INT )
{
Assert( 0 );
Warning( "*** Converter error - expected element \"%s\" to contain int attribute \"%s\"!\n", pElementInternal->GetName(), pNewName );
Warning( "*** - if you get this error, the converter is out of sync with the element library!\n" );
return;
}
}
else
{
#endif
// no factories installed - most likely from within dmxconvert.exe
// ie we're just working with CDmElement subclasses, so it's safe to add attributes
pNewAttr = pElementInternal->AddAttribute( pNewName, AT_INT );
if ( !pNewAttr )
{
Assert( 0 );
Warning( "*** Converter error - element \"%s\" already has a non-int attribute \"%s\"!\n", pElementInternal->GetName(), pNewName );
return;
}
#if 0
}
#endif
pNewAttr->SetValue< int >( floor( time * 10000 + 0.5f ) );
}
//-----------------------------------------------------------------------------
// Fixes up a single timeframe
//-----------------------------------------------------------------------------
void CImportSFMV1::FixupTimeframe( CDmElement *pElementInternal )
{
ConvertTimeAttribute( pElementInternal, "start", "startTime" );
ConvertTimeAttribute( pElementInternal, "duration", "durationTime" );
ConvertTimeAttribute( pElementInternal, "offset", "offsetTime" );
}
//-----------------------------------------------------------------------------
// Fixes up a single log - converting from int milliseconds to int tenths-of-a-millisecond
//-----------------------------------------------------------------------------
void CImportSFMV1::FixupLog( CDmElement *pElementInternal )
{
CDmAttribute *pAttr = pElementInternal->GetAttribute( "times" );
if ( !pAttr )
{
Warning( "*** Problem in file encountered!\n" );
Warning( "*** Log \"%s\" is missing attribute \"%s\"!\n", pElementInternal->GetName(), "times" );
return;
}
if ( pAttr->GetType() != AT_INT_ARRAY )
{
Warning( "*** Problem in file encountered!\n" );
Warning( "*** Log \"%s\" has attribute \"%s\" with an unexpected type (expected int array)!\n", pElementInternal->GetName(), "times" );
return;
}
CDmrArray<int> array( pAttr );
int c = array.Count();
for ( int i = 0; i < c; ++i )
{
// convert all log times from int milliseconds to int tenths-of-a-millisecond
array.Set( i, 10 * array[i] );
}
}