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.

310 lines
11 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #ifndef DMXELEMENT_H
  7. #define DMXELEMENT_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "datamodel/dmattributetypes.h"
  12. #include "tier1/utlvector.h"
  13. #include "tier1/utlrbtree.h"
  14. #include "tier1/utlsymbol.h"
  15. #include "tier1/mempool.h"
  16. #include "tier1/UtlSortVector.h"
  17. #include "dmxloader/dmxattribute.h"
  18. //-----------------------------------------------------------------------------
  19. // Sort functor class for attributes
  20. //-----------------------------------------------------------------------------
  21. class CDmxAttributeLess
  22. {
  23. public:
  24. bool Less( const CDmxAttribute * pAttribute1, const CDmxAttribute *pAttribute2, void *pContext )
  25. {
  26. return pAttribute1->GetNameSymbol() < pAttribute2->GetNameSymbol();
  27. }
  28. };
  29. //-----------------------------------------------------------------------------
  30. // Used to unpack elements into a structure. Does not recurse
  31. // Also does not work with arrays.
  32. //-----------------------------------------------------------------------------
  33. struct DmxElementUnpackStructure_t
  34. {
  35. const char *m_pAttributeName;
  36. const char *m_pDefaultString;
  37. DmAttributeType_t m_AttributeType;
  38. int m_nOffset;
  39. int m_nSize;
  40. const void *m_pUserData; // If you want to associate some app-specific data with each field
  41. };
  42. #define DECLARE_DMXELEMENT_UNPACK() \
  43. template <typename T> friend DmxElementUnpackStructure_t *DmxElementUnpackInit(T *);
  44. #define BEGIN_DMXELEMENT_UNPACK( _structName ) \
  45. template <typename T> DmxElementUnpackStructure_t *DmxElementUnpackInit(T *); \
  46. template <> DmxElementUnpackStructure_t *DmxElementUnpackInit<_structName>( _structName * ); \
  47. namespace _structName##_UnpackInit \
  48. { \
  49. static DmxElementUnpackStructure_t *s_pUnpack = DmxElementUnpackInit( (_structName *)NULL ); \
  50. } \
  51. \
  52. template <> DmxElementUnpackStructure_t *DmxElementUnpackInit<_structName>( _structName * ) \
  53. { \
  54. typedef _structName DestStructType_t; \
  55. static DmxElementUnpackStructure_t unpack[] = \
  56. { \
  57. #define DMXELEMENT_UNPACK_FLTX4( _attributeName, _defaultString, _varName ) \
  58. { _attributeName, _defaultString, CDmAttributeInfo<float>::AttributeType(), (int)offsetof( DestStructType_t, _varName ), sizeof( fltx4 ), NULL },
  59. #define DMXELEMENT_UNPACK_FIELD( _attributeName, _defaultString, _type, _varName ) \
  60. { _attributeName, _defaultString, CDmAttributeInfo<_type>::AttributeType(), (int)offsetof( DestStructType_t, _varName ), sizeof( ((DestStructType_t *)0)->_varName), NULL },
  61. #define DMXELEMENT_UNPACK_FIELD_STRING( _attributeName, _defaultString, _varName ) \
  62. { _attributeName, _defaultString, AT_STRING, offsetof( DestStructType_t, _varName ), sizeof( ((DestStructType_t *)0)->_varName), NULL },
  63. #define DMXELEMENT_UNPACK_FIELD_USERDATA( _attributeName, _defaultString, _type, _varName, _userData ) \
  64. { _attributeName, _defaultString, CDmAttributeInfo<_type>::AttributeType(), (int)offsetof( DestStructType_t, _varName ), sizeof( ((DestStructType_t *)0)->_varName), _userData },
  65. #define DMXELEMENT_UNPACK_FIELD_STRING_USERDATA( _attributeName, _defaultString, _varName, _userData ) \
  66. { _attributeName, _defaultString, AT_STRING, (int)offsetof( DestStructType_t, _varName ), sizeof( ((DestStructType_t *)0)->_varName), _userData },
  67. #define END_DMXELEMENT_UNPACK( _structName, _varName ) \
  68. { NULL, NULL, AT_UNKNOWN, 0, 0, NULL } \
  69. }; \
  70. return unpack; \
  71. } \
  72. DmxElementUnpackStructure_t *_varName = _structName##_UnpackInit::s_pUnpack;
  73. #define END_DMXELEMENT_UNPACK_TEMPLATE( _structName, _varName ) \
  74. { NULL, NULL, AT_UNKNOWN, 0, 0, NULL } \
  75. }; \
  76. return unpack; \
  77. } \
  78. template<> DmxElementUnpackStructure_t *_varName = _structName##_UnpackInit::s_pUnpack;
  79. //-----------------------------------------------------------------------------
  80. // Element used to read dmx files from mod code. Similar to keyvalues.
  81. //-----------------------------------------------------------------------------
  82. class CDmxElement
  83. {
  84. DECLARE_DMX_ALLOCATOR( );
  85. public:
  86. bool HasAttribute( const char *pAttributeName ) const;
  87. CDmxAttribute *GetAttribute( const char *pAttributeName );
  88. const CDmxAttribute *GetAttribute( const char *pAttributeName ) const;
  89. int AttributeCount() const;
  90. CDmxAttribute *GetAttribute( int nIndex );
  91. const CDmxAttribute *GetAttribute( int nIndex ) const;
  92. CUtlSymbol GetType() const;
  93. const char* GetTypeString() const;
  94. const char* GetName() const;
  95. const DmObjectId_t &GetId() const;
  96. // Add+remove+rename can only occur during lock
  97. // NOTE: AddAttribute will find or add; returning an existing attribute if
  98. // one with the appropriate name exists
  99. void LockForChanges( bool bLock );
  100. CDmxAttribute *AddAttribute( const char *pAttributeName );
  101. void RemoveAttribute( const char *pAttributeName );
  102. void RemoveAttributeByPtr( CDmxAttribute *pAttribute );
  103. void RemoveAllAttributes();
  104. void RenameAttribute( const char *pAttributeName, const char *pNewName );
  105. // Simple methods to read attributes
  106. const char *GetValueString( const char *pAttributeName ) const;
  107. template< class T > const T& GetValue( const char *pAttributeName ) const;
  108. template< class T > const T& GetValue( const char *pAttributeName, const T& defaultValue ) const;
  109. template< class T > const CUtlVector<T>& GetArray( const char *pAttributeName ) const;
  110. template< class T > const CUtlVector<T>& GetArray( const char *pAttributeName, const CUtlVector<T>& defaultValue ) const;
  111. // Set methods
  112. CDmxAttribute* SetValue( const char *pAttributeName, const char *pString );
  113. CDmxAttribute* SetValue( const char *pAttributeName, void *pBuffer, int nLen );
  114. template< class T > CDmxAttribute* SetValue( const char *pAttributeName, const T& value );
  115. // Method to unpack data into a structure
  116. void UnpackIntoStructure( void *pData, size_t DataSizeInBytes, const DmxElementUnpackStructure_t *pUnpack ) const;
  117. // Creates attributes based on the unpack structure
  118. template <typename T>
  119. void AddAttributesFromStructure( const T *pData, const DmxElementUnpackStructure_t *pUnpack )
  120. {
  121. AddAttributesFromStructure_Internal( pData, sizeof(T), pUnpack );
  122. }
  123. private:
  124. void AddAttributesFromStructure_Internal( const void *pData, size_t byteCount, const DmxElementUnpackStructure_t *pUnpack );
  125. typedef CUtlSortVector< CDmxAttribute*, CDmxAttributeLess > AttributeList_t;
  126. CDmxElement( const char *pType );
  127. ~CDmxElement();
  128. // Removes all elements recursively
  129. void RemoveAllElementsRecursive();
  130. // Adds elements to delete to the deletion list
  131. void AddElementsToDelete( CUtlVector< CDmxElement * >& elementsToDelete );
  132. // Sorts the vector when a change has occurred
  133. void Resort( ) const;
  134. // Finds an attribute by name
  135. int FindAttribute( const char *pAttributeName ) const;
  136. int FindAttribute( CUtlSymbol attributeName ) const;
  137. // Sets the object id
  138. void SetId( const DmObjectId_t &id );
  139. // Are we locked?
  140. bool IsLocked() const;
  141. AttributeList_t m_Attributes;
  142. DmObjectId_t m_Id; // We need this strictly because we support serialization
  143. CUtlSymbol m_Type;
  144. char m_nLockCount;
  145. mutable bool m_bResortNeeded : 1;
  146. bool m_bIsMarkedForDeletion : 1;
  147. static CUtlSymbolTableMT s_TypeSymbols;
  148. friend class CDmxSerializer;
  149. friend class CDmxSerializerKeyValues2;
  150. friend void CleanupDMX( CDmxElement* pElement );
  151. friend CDmxElement* CreateDmxElement( const char *pType );
  152. };
  153. //-----------------------------------------------------------------------------
  154. // inline methods
  155. //-----------------------------------------------------------------------------
  156. // Are we locked?
  157. inline bool CDmxElement::IsLocked() const
  158. {
  159. return m_nLockCount > 0;
  160. }
  161. inline const char *CDmxElement::GetValueString( const char *pAttributeName ) const
  162. {
  163. const CDmxAttribute* pAttribute = GetAttribute( pAttributeName );
  164. if ( pAttribute )
  165. return pAttribute->GetValueString();
  166. return "";
  167. }
  168. template< class T >
  169. inline const T& CDmxElement::GetValue( const char *pAttributeName ) const
  170. {
  171. const CDmxAttribute* pAttribute = GetAttribute( pAttributeName );
  172. if ( pAttribute )
  173. return pAttribute->GetValue<T>();
  174. static T defaultValue;
  175. CDmAttributeInfo<T>::SetDefaultValue( defaultValue );
  176. return defaultValue;
  177. }
  178. template< class T >
  179. inline const T& CDmxElement::GetValue( const char *pAttributeName, const T& defaultValue ) const
  180. {
  181. const CDmxAttribute* pAttribute = GetAttribute( pAttributeName );
  182. if ( pAttribute )
  183. return pAttribute->GetValue<T>();
  184. return defaultValue;
  185. }
  186. template< class T >
  187. inline const CUtlVector<T>& CDmxElement::GetArray( const char *pAttributeName ) const
  188. {
  189. const CDmxAttribute* pAttribute = GetAttribute( pAttributeName );
  190. if ( pAttribute )
  191. return pAttribute->GetArray<T>();
  192. static CUtlVector<T> defaultValue;
  193. return defaultValue;
  194. }
  195. template< class T >
  196. inline const CUtlVector<T>& CDmxElement::GetArray( const char *pAttributeName, const CUtlVector<T>& defaultValue ) const
  197. {
  198. const CDmxAttribute* pAttribute = GetAttribute( pAttributeName );
  199. if ( pAttribute )
  200. return pAttribute->GetArray<T>();
  201. return defaultValue;
  202. }
  203. //-----------------------------------------------------------------------------
  204. // Creates a dmx element
  205. //-----------------------------------------------------------------------------
  206. CDmxElement* CreateDmxElement( const char *pType );
  207. //-----------------------------------------------------------------------------
  208. // Helper class to lock elements for changes
  209. //-----------------------------------------------------------------------------
  210. class CDmxElementModifyScope
  211. {
  212. public:
  213. CDmxElementModifyScope( CDmxElement *pElement ) : m_pElement( pElement )
  214. {
  215. m_pElement->LockForChanges( true );
  216. }
  217. ~CDmxElementModifyScope()
  218. {
  219. Release();
  220. }
  221. void Release()
  222. {
  223. if ( m_pElement )
  224. {
  225. m_pElement->LockForChanges( false );
  226. m_pElement = NULL;
  227. }
  228. }
  229. private:
  230. CDmxElement *m_pElement;
  231. };
  232. //-----------------------------------------------------------------------------
  233. // Set methods
  234. //-----------------------------------------------------------------------------
  235. inline CDmxAttribute* CDmxElement::SetValue( const char *pAttributeName, const char *pString )
  236. {
  237. CDmxElementModifyScope modify( this );
  238. CDmxAttribute *pAttribute = AddAttribute( pAttributeName );
  239. pAttribute->SetValue( pString );
  240. return pAttribute;
  241. }
  242. inline CDmxAttribute* CDmxElement::SetValue( const char *pAttributeName, void *pBuffer, int nLen )
  243. {
  244. CDmxElementModifyScope modify( this );
  245. CDmxAttribute *pAttribute = AddAttribute( pAttributeName );
  246. pAttribute->SetValue( pBuffer, nLen );
  247. return pAttribute;
  248. }
  249. template< class T >
  250. inline CDmxAttribute* CDmxElement::SetValue( const char *pAttributeName, const T& value )
  251. {
  252. CDmxElementModifyScope modify( this );
  253. CDmxAttribute *pAttribute = AddAttribute( pAttributeName );
  254. pAttribute->SetValue( value );
  255. return pAttribute;
  256. }
  257. #endif // DMXELEMENT_H