Team Fortress 2 Source Code as on 22/4/2020
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.

219 lines
7.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "dmserializers.h"
  7. #include "dmebaseimporter.h"
  8. #include "datamodel/idatamodel.h"
  9. #include "datamodel/dmattribute.h"
  10. #include "datamodel/dmelement.h"
  11. #include <math.h>
  12. //-----------------------------------------------------------------------------
  13. // Format converter
  14. //-----------------------------------------------------------------------------
  15. class CImportSFMV1 : public CSFMBaseImporter
  16. {
  17. typedef CSFMBaseImporter BaseClass;
  18. public:
  19. CImportSFMV1( char const *formatName, char const *nextFormatName );
  20. private:
  21. virtual bool DoFixup( CDmElement *pSourceRoot );
  22. // Fixes up a single time attribute - converting from float seconds to int tenths-of-a-millisecond
  23. void ConvertTimeAttribute( CDmElement *pElementInternal, const char *pOldName, const char *pNewName );
  24. // Fixes up a single timeframe
  25. void FixupTimeframe( CDmElement *pElementInternal );
  26. // Fixes up a single log - converting from int milliseconds to int tenths-of-a-millisecond
  27. void FixupLog( CDmElement *pElementInternal );
  28. CUtlRBTree< CDmElement*, int > m_fixedElements;
  29. };
  30. //-----------------------------------------------------------------------------
  31. // Singleton instance
  32. //-----------------------------------------------------------------------------
  33. static CImportSFMV1 s_ImportDmxV1( "sfm_v1", "sfm_v2" );
  34. void InstallSFMV1Importer( IDataModel *pFactory )
  35. {
  36. pFactory->AddLegacyUpdater( &s_ImportDmxV1 );
  37. }
  38. //-----------------------------------------------------------------------------
  39. // Constructor
  40. //-----------------------------------------------------------------------------
  41. CImportSFMV1::CImportSFMV1( char const *formatName, char const *nextFormatName ) :
  42. BaseClass( formatName, nextFormatName )
  43. {
  44. m_fixedElements.SetLessFunc( DefLessFunc( CDmElement * ) );
  45. }
  46. //-----------------------------------------------------------------------------
  47. // Fixes up all elements
  48. //-----------------------------------------------------------------------------
  49. bool CImportSFMV1::DoFixup( CDmElement *pElementInternal )
  50. {
  51. if ( !pElementInternal )
  52. return true;
  53. if ( m_fixedElements.Find( pElementInternal ) != m_fixedElements.InvalidIndex() )
  54. return true;
  55. m_fixedElements.Insert( pElementInternal );
  56. const char *pType = pElementInternal->GetTypeString();
  57. if ( !Q_strcmp( pType, "DmeTimeFrame" ) )
  58. {
  59. FixupTimeframe( pElementInternal );
  60. }
  61. else if ( !Q_strcmp( pType, "DmeLog" ) ||
  62. !Q_strcmp( pType, "DmeIntLog" ) ||
  63. !Q_strcmp( pType, "DmeFloatLog" ) ||
  64. !Q_strcmp( pType, "DmeBoolLog" ) ||
  65. !Q_strcmp( pType, "DmeColorLog" ) ||
  66. !Q_strcmp( pType, "DmeVector2Log" ) ||
  67. !Q_strcmp( pType, "DmeVector3Log" ) ||
  68. !Q_strcmp( pType, "DmeVector4Log" ) ||
  69. !Q_strcmp( pType, "DmeQAngleLog" ) ||
  70. !Q_strcmp( pType, "DmeQuaternionLog" ) ||
  71. !Q_strcmp( pType, "DmeVMatrixLog" ) )
  72. {
  73. FixupLog( pElementInternal );
  74. }
  75. for ( CDmAttribute *pAttribute = pElementInternal->FirstAttribute(); pAttribute; pAttribute = pAttribute->NextAttribute() )
  76. {
  77. if ( pAttribute->GetType() == AT_ELEMENT )
  78. {
  79. CDmElement *pElement = pAttribute->GetValueElement<CDmElement>( );
  80. DoFixup( pElement );
  81. continue;
  82. }
  83. if ( pAttribute->GetType() == AT_ELEMENT_ARRAY )
  84. {
  85. CDmrElementArray<> array( pAttribute );
  86. int nCount = array.Count();
  87. for ( int i = 0; i < nCount; ++i )
  88. {
  89. CDmElement *pChild = array[ i ];
  90. DoFixup( pChild );
  91. }
  92. continue;
  93. }
  94. }
  95. return true;
  96. }
  97. //-----------------------------------------------------------------------------
  98. // Fixes up a single time attribute - converting from float seconds to int tenths-of-a-millisecond
  99. //-----------------------------------------------------------------------------
  100. void CImportSFMV1::ConvertTimeAttribute( CDmElement *pElementInternal, const char *pOldName, const char *pNewName )
  101. {
  102. float time = 0.0f;
  103. CDmAttribute *pOldAttr = pElementInternal->GetAttribute( pOldName );
  104. if ( !pOldAttr )
  105. {
  106. Warning( "*** Problem in file encountered!\n" );
  107. Warning( "*** TimeFrame \"%s\" is missing attribute \"%s\"!\n", pElementInternal->GetName(), pOldName );
  108. Warning( "*** Setting new attribute \"%s\" to 0\n", pNewName );
  109. }
  110. else if ( pOldAttr->GetType() != AT_FLOAT )
  111. {
  112. Warning( "*** Problem in file encountered!\n" );
  113. Warning( "*** TimeFrame \"%s\" has attribute \"%s\" with an unexpected type (expected float)!\n", pElementInternal->GetName(), pOldName );
  114. }
  115. else
  116. {
  117. time = pOldAttr->GetValue< float >();
  118. pElementInternal->RemoveAttribute( pOldName );
  119. }
  120. CDmAttribute *pNewAttr = NULL;
  121. // this is disabled because even dmxconvert installs *some* movieobjects factories, when it probably shouldn't
  122. // the method of installing movieobjects factories will change at some point in the future, and we can turn on this safety check then
  123. #if 0
  124. int i = g_pDataModel->GetFirstFactory();
  125. if ( g_pDataModel->IsValidFactory( i ) )
  126. {
  127. // factories installed - most likely from within movieobjects.lib
  128. // ie there may be different ways of allocating attributes, so it's not safe to add them here
  129. pNewAttr = pElementInternal->GetAttribute( pNewName );
  130. if ( !pNewAttr || pNewAttr->GetType() != AT_INT )
  131. {
  132. Assert( 0 );
  133. Warning( "*** Converter error - expected element \"%s\" to contain int attribute \"%s\"!\n", pElementInternal->GetName(), pNewName );
  134. Warning( "*** - if you get this error, the converter is out of sync with the element library!\n" );
  135. return;
  136. }
  137. }
  138. else
  139. {
  140. #endif
  141. // no factories installed - most likely from within dmxconvert.exe
  142. // ie we're just working with CDmElement subclasses, so it's safe to add attributes
  143. pNewAttr = pElementInternal->AddAttribute( pNewName, AT_INT );
  144. if ( !pNewAttr )
  145. {
  146. Assert( 0 );
  147. Warning( "*** Converter error - element \"%s\" already has a non-int attribute \"%s\"!\n", pElementInternal->GetName(), pNewName );
  148. return;
  149. }
  150. #if 0
  151. }
  152. #endif
  153. pNewAttr->SetValue< int >( floor( time * 10000 + 0.5f ) );
  154. }
  155. //-----------------------------------------------------------------------------
  156. // Fixes up a single timeframe
  157. //-----------------------------------------------------------------------------
  158. void CImportSFMV1::FixupTimeframe( CDmElement *pElementInternal )
  159. {
  160. ConvertTimeAttribute( pElementInternal, "start", "startTime" );
  161. ConvertTimeAttribute( pElementInternal, "duration", "durationTime" );
  162. ConvertTimeAttribute( pElementInternal, "offset", "offsetTime" );
  163. }
  164. //-----------------------------------------------------------------------------
  165. // Fixes up a single log - converting from int milliseconds to int tenths-of-a-millisecond
  166. //-----------------------------------------------------------------------------
  167. void CImportSFMV1::FixupLog( CDmElement *pElementInternal )
  168. {
  169. CDmAttribute *pAttr = pElementInternal->GetAttribute( "times" );
  170. if ( !pAttr )
  171. {
  172. Warning( "*** Problem in file encountered!\n" );
  173. Warning( "*** Log \"%s\" is missing attribute \"%s\"!\n", pElementInternal->GetName(), "times" );
  174. return;
  175. }
  176. if ( pAttr->GetType() != AT_INT_ARRAY )
  177. {
  178. Warning( "*** Problem in file encountered!\n" );
  179. Warning( "*** Log \"%s\" has attribute \"%s\" with an unexpected type (expected int array)!\n", pElementInternal->GetName(), "times" );
  180. return;
  181. }
  182. CDmrArray<int> array( pAttr );
  183. int c = array.Count();
  184. for ( int i = 0; i < c; ++i )
  185. {
  186. // convert all log times from int milliseconds to int tenths-of-a-millisecond
  187. array.Set( i, 10 * array[i] );
  188. }
  189. }