aboutsummaryrefslogtreecommitdiff
path: root/sp/src/public/datamodel
diff options
context:
space:
mode:
authorJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
committerJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
commit39ed87570bdb2f86969d4be821c94b722dc71179 (patch)
treeabc53757f75f40c80278e87650ea92808274aa59 /sp/src/public/datamodel
downloadsource-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz
source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip
First version of the SOurce SDK 2013
Diffstat (limited to 'sp/src/public/datamodel')
-rw-r--r--sp/src/public/datamodel/attributeflags.h35
-rw-r--r--sp/src/public/datamodel/dmattribute.h768
-rw-r--r--sp/src/public/datamodel/dmattributetypes.h316
-rw-r--r--sp/src/public/datamodel/dmattributevar.h1481
-rw-r--r--sp/src/public/datamodel/dmehandle.h243
-rw-r--r--sp/src/public/datamodel/dmelement.h618
-rw-r--r--sp/src/public/datamodel/dmelementfactoryhelper.h190
-rw-r--r--sp/src/public/datamodel/dmelementhandle.h47
-rw-r--r--sp/src/public/datamodel/dmvar.h93
-rw-r--r--sp/src/public/datamodel/idatamodel.h938
10 files changed, 4729 insertions, 0 deletions
diff --git a/sp/src/public/datamodel/attributeflags.h b/sp/src/public/datamodel/attributeflags.h
new file mode 100644
index 00000000..e074df37
--- /dev/null
+++ b/sp/src/public/datamodel/attributeflags.h
@@ -0,0 +1,35 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef ATTRIBUTEFLAGS_H
+#define ATTRIBUTEFLAGS_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+enum
+{
+ // NOTE: The first 5 flags bits are reserved for attribute type
+ FATTRIB_TYPEMASK = 0x1F,
+
+ FATTRIB_READONLY = (1<<5), // Don't allow editing value in editors
+ FATTRIB_DONTSAVE = (1<<6), // Don't persist to .dmx file
+ FATTRIB_DIRTY = (1<<7), // Indicates the attribute has been changed since the resolve phase
+ FATTRIB_HAS_CALLBACK = (1<<8), // Indicates that this will notify its owner and/or other elements when it changes
+ FATTRIB_EXTERNAL = (1<<9), // Indicates this attribute's data is externally owned (in a CDmElement somewhere)
+ FATTRIB_TOPOLOGICAL = (1<<10), // Indicates this attribute effects the scene's topology (ie it's an attribute name or element)
+ FATTRIB_MUSTCOPY = (1<<11), // parent element must make a new copy during CopyInto, even for shallow copy
+ FATTRIB_NEVERCOPY = (1<<12), // parent element shouldn't make a new copy during CopyInto, even for deep copy
+ FATTRIB_STANDARD = (1<<13), // This flag is set if it's a "standard" attribute, namely "name"
+ FATTRIB_USERDEFINED = (1<<14), // This flag is used to sort attributes in the element properties view. User defined flags come last.
+ FATTRIB_NODUPLICATES = (1<<15),// For element array types, disallows duplicate values from being inserted into the array.
+ FATTRIB_HAS_ARRAY_CALLBACK = (1<<16), // Indicates that this will notify its owner and/or other elements array elements changes. Note that when elements shift (say, inserting at head, or fast remove), callbacks are not executed for these elements.
+ FATTRIB_HAS_PRE_CALLBACK = (1<<17), // Indicates that this will notify its owner and/or other elements right before it changes
+ FATTRIB_OPERATOR_DIRTY = (1<<18),// Used and cleared only by operator phase of datamodel
+};
+
+#endif // ATTRIBUTEFLAGS_H
diff --git a/sp/src/public/datamodel/dmattribute.h b/sp/src/public/datamodel/dmattribute.h
new file mode 100644
index 00000000..5bf016f0
--- /dev/null
+++ b/sp/src/public/datamodel/dmattribute.h
@@ -0,0 +1,768 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef DMATTRIBUTE_H
+#define DMATTRIBUTE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "datamodel/attributeflags.h"
+#include "datamodel/idatamodel.h"
+#include "datamodel/dmattributetypes.h"
+#include "datamodel/dmelement.h"
+#include "datamodel/dmvar.h"
+#include "tier1/utlhash.h"
+
+//-----------------------------------------------------------------------------
+// Fast dynamic cast
+//-----------------------------------------------------------------------------
+template< class E >
+inline E *CastElement( CDmElement *pElement )
+{
+ if ( pElement && pElement->IsA( E::GetStaticTypeSymbol() ) )
+ return static_cast< E* >( pElement );
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// type-safe element creation and accessor helpers - infers type name string from actual type
+//-----------------------------------------------------------------------------
+template< class E >
+inline E *GetElement( DmElementHandle_t hElement )
+{
+ CDmElement *pElement = g_pDataModel->GetElement( hElement );
+ return CastElement< E >( pElement );
+}
+
+//-----------------------------------------------------------------------------
+// Typesafe element creation + destruction
+//-----------------------------------------------------------------------------
+template< class E >
+inline E *CreateElement( const char *pObjectName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL )
+{
+ return GetElement< E >( g_pDataModel->CreateElement( E::GetStaticTypeSymbol(), pObjectName, fileid, pObjectID ) );
+}
+
+template< class E >
+inline E *CreateElement( const char *pElementType, const char *pObjectName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL )
+{
+ return GetElement< E >( g_pDataModel->CreateElement( pElementType, pObjectName, fileid, pObjectID ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Used for attribute change callbacks
+//-----------------------------------------------------------------------------
+typedef unsigned short DmMailingList_t;
+enum
+{
+ DMMAILINGLIST_INVALID = (DmMailingList_t)~0
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: A general purpose pAttribute. Eventually will be extensible to arbitrary user types
+//-----------------------------------------------------------------------------
+class CDmAttribute
+{
+public:
+ // Returns the type
+ DmAttributeType_t GetType() const;
+ const char *GetTypeString() const;
+ template< class T > bool IsA() const;
+
+ // Returns the name. NOTE: The utlsymbol
+ // can be turned into a string by using g_pDataModel->String();
+ const char *GetName() const;
+ UtlSymId_t GetNameSymbol() const;
+ void SetName( const char *newName );
+
+ // Gets the attribute value
+ // NOTE: GetValueUntyped is used with GetType() for use w/ SetValue( type, void* )
+ template< class T > const T& GetValue() const;
+ template< class T > const T& GetValue( const T& defaultValue ) const;
+ const char *GetValueString() const;
+ template< class E > E *GetValueElement() const;
+ const void *GetValueUntyped() const;
+
+ // Sets the attribute value
+ template< class T > void SetValue( const T &value );
+ template< class E > void SetValue( E* pValue );
+ void SetValue( const void *pValue, size_t nSize );
+
+ // Copies w/ type conversion (if possible) from another attribute
+ void SetValue( const CDmAttribute *pAttribute );
+ void SetValue( CDmAttribute *pAttribute );
+ void SetValue( DmAttributeType_t valueType, const void *pValue );
+
+ // Sets the attribute to its default value based on its type
+ void SetToDefaultValue();
+
+ // Convert to and from string
+ void SetValueFromString( const char *pValue );
+ const char *GetValueAsString( char *pBuffer, size_t nBufLen ) const;
+
+ // Used for element and element array attributes; it specifies which type of
+ // elements are valid to be referred to by this attribute
+ void SetElementTypeSymbol( UtlSymId_t typeSymbol );
+ UtlSymId_t GetElementTypeSymbol() const;
+
+ // Returns the next attribute
+ CDmAttribute *NextAttribute();
+ const CDmAttribute *NextAttribute() const;
+
+ // Returns the owner
+ CDmElement *GetOwner();
+
+ // Methods related to flags
+ void AddFlag( int flags );
+ void RemoveFlag( int flags );
+ void ClearFlags();
+ int GetFlags() const;
+ bool IsFlagSet( int flags ) const;
+
+ // Serialization
+ bool Serialize( CUtlBuffer &buf ) const;
+ bool Unserialize( CUtlBuffer &buf );
+
+ // Serialization of a single element.
+ // First version of UnserializeElement adds to tail if it worked
+ // Second version overwrites, but does not add, the element at the specified index
+ bool SerializeElement( int nElement, CUtlBuffer &buf ) const;
+ bool UnserializeElement( CUtlBuffer &buf );
+ bool UnserializeElement( int nElement, CUtlBuffer &buf );
+
+ // Does this attribute serialize on multiple lines?
+ bool SerializesOnMultipleLines() const;
+
+ // Get the attribute/create an attribute handle
+ DmAttributeHandle_t GetHandle( bool bCreate = true );
+
+ // Notify external elements upon change ( Calls OnAttributeChanged )
+ // Pass false here to stop notification
+ void NotifyWhenChanged( DmElementHandle_t h, bool bNotify );
+
+ // estimate memory overhead
+ int EstimateMemoryUsage( TraversalDepth_t depth ) const;
+
+private:
+ // Class factory
+ static CDmAttribute *CreateAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName );
+ static CDmAttribute *CreateExternalAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName, void *pExternalMemory );
+ static void DestroyAttribute( CDmAttribute *pAttribute );
+
+ // Constructor, destructor
+ CDmAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName );
+ CDmAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName, void *pMemory );
+ ~CDmAttribute();
+
+ // Used when constructing CDmAttributes
+ void Init( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName );
+
+ // Used when shutting down, indicates DmAttributeHandle_t referring to this are invalid
+ void InvalidateHandle();
+
+ // Used when shutting down, indicates no more change notifications will be sent to listening elements
+ void CleanupMailingList();
+
+ // Called when the attribute changes
+ void PreChanged();
+ void OnChanged( bool bArrayCountChanged = false, bool bIsTopological = false );
+
+ // Is modification allowed in this phase?
+ bool ModificationAllowed() const;
+
+ // Mark the attribute as being dirty
+ bool MarkDirty();
+
+ // Is the data inline in a containing element class?
+ bool IsDataInline() const;
+
+ // Allocates, frees internal data storage
+ void CreateAttributeData();
+ void DeleteAttributeData();
+
+ // Gets at the internal data storage
+ void* GetAttributeData();
+ const void* GetAttributeData() const;
+ template < class T > typename CDmAttributeInfo< T >::StorageType_t* GetData();
+ template < class T > const typename CDmAttributeInfo< T >::StorageType_t* GetData() const;
+ template < class T > typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* GetArrayData();
+ template < class T > const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* GetArrayData() const;
+
+ // Used by CDmElement to manage the list of attributes it owns
+ CDmAttribute **GetNextAttributeRef();
+
+ // Implementational function used for memory consumption estimation computation
+ int EstimateMemoryUsageInternal( CUtlHash< DmElementHandle_t > &visited, TraversalDepth_t depth, int *pCategories ) const;
+
+ // Called by elements after unserialization of their attributes is complete
+ void OnUnserializationFinished();
+
+ template< class T > bool IsTypeConvertable() const;
+ template< class T > bool ShouldModify( const T& src );
+ template< class T > void CopyData( const T& src );
+ template< class T > void CopyDataOut( T& dest ) const;
+
+private:
+ CDmAttribute *m_pNext;
+ void *m_pData;
+ CDmElement *m_pOwner;
+ int m_nFlags;
+ DmAttributeHandle_t m_Handle;
+ CUtlSymbol m_Name;
+ DmMailingList_t m_hMailingList;
+
+ friend class CDmElement;
+ friend class CDmAttributeAccessor;
+ template< class T > friend class CDmrElementArray;
+ template< class E > friend class CDmrElementArrayConst;
+ template< class T > friend class CDmaArrayAccessor;
+ template< class T, class B > friend class CDmrDecorator;
+ template< class T, class B > friend class CDmrDecoratorConst;
+ template< class T > friend class CDmArrayAttributeOp;
+};
+
+
+//-----------------------------------------------------------------------------
+// Inline methods
+//-----------------------------------------------------------------------------
+inline DmAttributeType_t CDmAttribute::GetType() const
+{
+ return (DmAttributeType_t)( m_nFlags & FATTRIB_TYPEMASK );
+}
+
+template< class T > inline bool CDmAttribute::IsA() const
+{
+ return GetType() == CDmAttributeInfo< T >::AttributeType();
+}
+
+inline const char *CDmAttribute::GetName() const
+{
+ return g_pDataModel->GetString( m_Name );
+}
+
+inline UtlSymId_t CDmAttribute::GetNameSymbol() const
+{
+ return m_Name;
+}
+
+
+//-----------------------------------------------------------------------------
+// Iteration
+//-----------------------------------------------------------------------------
+inline CDmAttribute *CDmAttribute::NextAttribute()
+{
+ return m_pNext;
+}
+
+inline const CDmAttribute *CDmAttribute::NextAttribute() const
+{
+ return m_pNext;
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the owner
+//-----------------------------------------------------------------------------
+inline CDmElement *CDmAttribute::GetOwner()
+{
+ return m_pOwner;
+}
+
+
+//-----------------------------------------------------------------------------
+// Value getting methods
+//-----------------------------------------------------------------------------
+template< class T >
+inline const T& CDmAttribute::GetValue( const T& defaultValue ) const
+{
+ if ( GetType() == ( DmAttributeType_t )( CDmAttributeInfo< T >::ATTRIBUTE_TYPE ) )
+ return *reinterpret_cast< const T* >( m_pData );
+
+ if ( IsTypeConvertable< T >() )
+ {
+ static T tempVal;
+ CopyDataOut( tempVal );
+ return tempVal;
+ }
+
+ Assert( 0 );
+ return defaultValue;
+}
+
+template< class T >
+inline const T& CDmAttribute::GetValue() const
+{
+ static CDmaVar< T > defaultVal;
+ return GetValue( defaultVal.Get() );
+}
+
+inline const char *CDmAttribute::GetValueString() const
+{
+ Assert( GetType() == AT_STRING );
+ if ( GetType() != AT_STRING )
+ return NULL;
+
+ return GetValue< CUtlString >();
+}
+
+// used with GetType() for use w/ SetValue( type, void* )
+inline const void* CDmAttribute::GetValueUntyped() const
+{
+ return m_pData;
+}
+
+template< class E >
+inline E* CDmAttribute::GetValueElement() const
+{
+ Assert( GetType() == AT_ELEMENT );
+ if ( GetType() == AT_ELEMENT )
+ return GetElement<E>( this->GetValue< DmElementHandle_t >() );
+ return NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Value setting methods
+//-----------------------------------------------------------------------------
+template< class E >
+inline void CDmAttribute::SetValue( E* pValue )
+{
+ Assert( GetType() == AT_ELEMENT );
+ if ( GetType() == AT_ELEMENT )
+ {
+ SetValue( pValue ? pValue->GetHandle() : DMELEMENT_HANDLE_INVALID );
+ }
+}
+
+template<>
+inline void CDmAttribute::SetValue( const char *pValue )
+{
+ int nLen = pValue ? Q_strlen( pValue ) + 1 : 0;
+ CUtlString str( pValue, nLen );
+ return SetValue( str );
+}
+
+template<>
+inline void CDmAttribute::SetValue( char *pValue )
+{
+ return SetValue( (const char *)pValue );
+}
+
+inline void CDmAttribute::SetValue( const void *pValue, size_t nSize )
+{
+ CUtlBinaryBlock buf( pValue, nSize );
+ return SetValue( buf );
+}
+
+
+//-----------------------------------------------------------------------------
+// Methods related to flags
+//-----------------------------------------------------------------------------
+inline void CDmAttribute::AddFlag( int nFlags )
+{
+ m_nFlags |= nFlags;
+}
+
+inline void CDmAttribute::RemoveFlag( int nFlags )
+{
+ m_nFlags &= ~nFlags;
+}
+
+inline void CDmAttribute::ClearFlags()
+{
+ m_nFlags = 0;
+}
+
+inline int CDmAttribute::GetFlags() const
+{
+ return m_nFlags;
+}
+
+inline bool CDmAttribute::IsFlagSet( int nFlags ) const
+{
+ return ( nFlags & m_nFlags ) ? true : false;
+}
+
+inline bool CDmAttribute::IsDataInline() const
+{
+ return !IsFlagSet(FATTRIB_EXTERNAL);
+}
+
+
+//-----------------------------------------------------------------------------
+// Gets at the internal data storage
+//-----------------------------------------------------------------------------
+inline void* CDmAttribute::GetAttributeData()
+{
+ return m_pData;
+}
+
+inline const void* CDmAttribute::GetAttributeData() const
+{
+ return m_pData;
+}
+
+template < class T >
+inline typename CDmAttributeInfo< T >::StorageType_t* CDmAttribute::GetData()
+{
+ return ( typename CDmAttributeInfo< T >::StorageType_t* )m_pData;
+}
+
+template < class T >
+inline typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* CDmAttribute::GetArrayData()
+{
+ return ( typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* )m_pData;
+}
+
+template < class T >
+inline const typename CDmAttributeInfo< T >::StorageType_t* CDmAttribute::GetData() const
+{
+ return ( const typename CDmAttributeInfo< T >::StorageType_t* )m_pData;
+}
+
+template < class T >
+inline const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* CDmAttribute::GetArrayData() const
+{
+ return ( const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* )m_pData;
+}
+
+
+//-----------------------------------------------------------------------------
+// Used by CDmElement to manage the list of attributes it owns
+//-----------------------------------------------------------------------------
+inline CDmAttribute **CDmAttribute::GetNextAttributeRef()
+{
+ return &m_pNext;
+}
+
+
+//-----------------------------------------------------------------------------
+// helper function for determining which attributes/elements to traverse during copy/find/save/etc.
+//-----------------------------------------------------------------------------
+inline bool ShouldTraverse( const CDmAttribute *pAttr, TraversalDepth_t depth )
+{
+ switch ( depth )
+ {
+ case TD_NONE:
+ return false;
+
+ case TD_SHALLOW:
+ if ( !pAttr->IsFlagSet( FATTRIB_MUSTCOPY ) )
+ return false;
+ // fall-through intentional
+ case TD_DEEP:
+ if ( pAttr->IsFlagSet( FATTRIB_NEVERCOPY ) )
+ return false;
+ // fall-through intentional
+ case TD_ALL:
+ return true;
+ }
+
+ Assert( 0 );
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Gets attributes
+//-----------------------------------------------------------------------------
+inline CDmAttribute *CDmElement::GetAttribute( const char *pAttributeName, DmAttributeType_t type )
+{
+ CDmAttribute *pAttribute = FindAttribute( pAttributeName );
+ if ( ( type != AT_UNKNOWN ) && pAttribute && ( pAttribute->GetType() != type ) )
+ return NULL;
+ return pAttribute;
+}
+
+inline const CDmAttribute *CDmElement::GetAttribute( const char *pAttributeName, DmAttributeType_t type ) const
+{
+ CDmAttribute *pAttribute = FindAttribute( pAttributeName );
+ if ( ( type != AT_UNKNOWN ) && pAttribute && ( pAttribute->GetType() != type ) )
+ return NULL;
+ return pAttribute;
+}
+
+
+//-----------------------------------------------------------------------------
+// AddAttribute calls
+//-----------------------------------------------------------------------------
+inline CDmAttribute *CDmElement::AddAttribute( const char *pAttributeName, DmAttributeType_t type )
+{
+ CDmAttribute *pAttribute = FindAttribute( pAttributeName );
+ if ( pAttribute )
+ return ( pAttribute->GetType() == type ) ? pAttribute : NULL;
+ pAttribute = CreateAttribute( pAttributeName, type );
+ return pAttribute;
+}
+
+template< class E > inline CDmAttribute *CDmElement::AddAttributeElement( const char *pAttributeName )
+{
+ CDmAttribute *pAttribute = AddAttribute( pAttributeName, AT_ELEMENT );
+ if ( !pAttribute )
+ return NULL;
+
+ // FIXME: If the attribute exists but has a different element type symbol, should we complain?
+ pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() );
+ return pAttribute;
+}
+
+template< class E > inline CDmAttribute *CDmElement::AddAttributeElementArray( const char *pAttributeName )
+{
+ CDmAttribute *pAttribute = AddAttribute( pAttributeName, AT_ELEMENT_ARRAY );
+ if ( !pAttribute )
+ return NULL;
+
+ // FIXME: If the attribute exists but has a different element type symbol, should we complain?
+ pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() );
+ return pAttribute;
+}
+
+//-----------------------------------------------------------------------------
+// GetValue methods
+//-----------------------------------------------------------------------------
+
+template< class T >
+inline const T& CDmElement::GetValue( const char *pAttributeName ) const
+{
+ static CDmaVar<T> defaultVal;
+ return GetValue( pAttributeName, defaultVal.Get() );
+}
+
+inline const char *CDmElement::GetValueString( const char *pAttributeName ) const
+{
+ return GetValue<CUtlString>( pAttributeName ).Get();
+}
+
+template< class E >
+inline E* CDmElement::GetValueElement( const char *pAttributeName ) const
+{
+ DmElementHandle_t h = GetValue< DmElementHandle_t >( pAttributeName );
+ return GetElement<E>( h );
+}
+
+
+template< class T >
+inline const T& CDmElement::GetValue( const char *pAttributeName, const T& defaultVal ) const
+{
+ const CDmAttribute *pAttribute = FindAttribute( pAttributeName );
+ if ( pAttribute != NULL )
+ return pAttribute->GetValue<T>();
+ return defaultVal;
+}
+
+//-----------------------------------------------------------------------------
+// SetValue methods
+//-----------------------------------------------------------------------------
+template< class T >
+inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const T& value )
+{
+ CDmAttribute *pAttribute = FindAttribute( pAttributeName );
+ if ( !pAttribute )
+ {
+ pAttribute = CreateAttribute( pAttributeName, CDmAttributeInfo<T>::AttributeType() );
+ }
+ if ( pAttribute )
+ {
+ pAttribute->SetValue( value );
+ return pAttribute;
+ }
+ return NULL;
+}
+
+template< class E >
+inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, E* pElement )
+{
+ DmElementHandle_t hElement = pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID;
+ return SetValue( pAttributeName, hElement );
+}
+
+template<>
+inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const char *pValue )
+{
+ int nLen = pValue ? Q_strlen( pValue ) + 1 : 0;
+ CUtlString str( pValue, nLen );
+ return SetValue( pAttributeName, str );
+}
+
+template<>
+inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, char *pValue )
+{
+ return SetValue( pAttributeName, (const char *)pValue );
+}
+
+inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const void *pValue, size_t nSize )
+{
+ CUtlBinaryBlock buf( pValue, nSize );
+ return SetValue( pAttributeName, buf );
+}
+
+
+//-----------------------------------------------------------------------------
+// AddValue methods( set value if not found )
+//-----------------------------------------------------------------------------
+template< class T >
+inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, const T& value )
+{
+ CDmAttribute *pAttribute = GetAttribute( pAttributeName );
+ if ( !pAttribute )
+ return SetValue( pAttributeName, value );
+ return pAttribute;
+}
+
+template< class E >
+inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, E* pElement )
+{
+ DmElementHandle_t hElement = pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID;
+ return InitValue( pAttributeName, hElement );
+}
+
+inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, const void *pValue, size_t size )
+{
+ CDmAttribute *pAttribute = GetAttribute( pAttributeName );
+ if ( !pAttribute )
+ return SetValue( pAttributeName, pValue, size );
+ return pAttribute;
+}
+
+template< class T >
+T *FindReferringElement( CDmElement *pElement, UtlSymId_t symAttrName, bool bMustBeInSameFile = true )
+{
+ DmAttributeReferenceIterator_t i = g_pDataModel->FirstAttributeReferencingElement( pElement->GetHandle() );
+ while ( i != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID )
+ {
+ CDmAttribute *pAttribute = g_pDataModel->GetAttribute( i );
+ CDmElement *pDmeParent = pAttribute->GetOwner();
+ if ( pDmeParent && pAttribute->GetNameSymbol() == symAttrName )
+ {
+ T *pParent = CastElement< T >( pDmeParent );
+ if ( pParent )
+ {
+ if ( !bMustBeInSameFile || ( pParent->GetFileId() == pElement->GetFileId() ) )
+ return pParent;
+ }
+ }
+ i = g_pDataModel->NextAttributeReferencingElement( i );
+ }
+
+ return NULL;
+}
+
+template< class T >
+T *FindAncestorReferencingElement( CDmElement *target )
+{
+ if ( !target )
+ return NULL;
+
+ for ( DmAttributeReferenceIterator_t it = g_pDataModel->FirstAttributeReferencingElement( target->GetHandle() );
+ it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
+ it = g_pDataModel->NextAttributeReferencingElement( it ) )
+ {
+ CDmAttribute *attr = g_pDataModel->GetAttribute( it );
+ Assert( attr );
+ CDmElement *element = attr->GetOwner();
+ Assert( element );
+ if ( !element )
+ continue;
+ T *t = CastElement< T >( element );
+ if ( !t )
+ continue;
+
+ return t;
+ }
+ return NULL;
+}
+
+template< class T >
+T *FindAncestorReferencingElement_R_Impl( CUtlRBTree< CDmElement * >& visited, CDmElement *check )
+{
+ if ( visited.Find( check ) != visited.InvalidIndex() )
+ return NULL;
+
+ visited.Insert( check );
+
+ // Pass one, see if it's in this ancestor list
+ DmAttributeReferenceIterator_t it;
+ for ( it = g_pDataModel->FirstAttributeReferencingElement( check->GetHandle() );
+ it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
+ it = g_pDataModel->NextAttributeReferencingElement( it ) )
+ {
+ CDmAttribute *attr = g_pDataModel->GetAttribute( it );
+ Assert( attr );
+ CDmElement *element = attr->GetOwner();
+ Assert( element );
+ if ( !element )
+ continue;
+ T *t = CastElement< T >( element );
+ if ( !t )
+ continue;
+
+ return t;
+ }
+
+ for ( it = g_pDataModel->FirstAttributeReferencingElement( check->GetHandle() );
+ it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
+ it = g_pDataModel->NextAttributeReferencingElement( it ) )
+ {
+ CDmAttribute *attr = g_pDataModel->GetAttribute( it );
+ Assert( attr );
+ CDmElement *element = attr->GetOwner();
+ Assert( element );
+ if ( !element )
+ continue;
+
+ T *found = FindAncestorReferencingElement_R_Impl< T >( visited, element );
+ if ( found )
+ return found;
+ }
+ return NULL;
+}
+
+
+template< class T >
+void FindAncestorsReferencingElement( CDmElement *target, CUtlVector< T* >& list )
+{
+ if ( !target )
+ return;
+
+ list.RemoveAll();
+ for ( DmAttributeReferenceIterator_t it = g_pDataModel->FirstAttributeReferencingElement( target->GetHandle() );
+ it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
+ it = g_pDataModel->NextAttributeReferencingElement( it ) )
+ {
+ CDmAttribute *attr = g_pDataModel->GetAttribute( it );
+ Assert( attr );
+ CDmElement *element = attr->GetOwner();
+ Assert( element );
+ if ( !element )
+ continue;
+ T* t = CastElement< T >( element );
+ if ( !t )
+ continue;
+
+ if ( list.Find( t ) != list.InvalidIndex() )
+ continue;
+
+ list.AddToTail( t );
+ }
+}
+
+
+template< class T >
+T *FindAncestorReferencingElement_R( CDmElement *target )
+{
+ if ( !target )
+ return NULL;
+
+ CUtlRBTree< CDmElement * > visited( 0, 0, DefLessFunc( CDmElement * ) );
+ return FindAncestorReferencingElement_R_Impl< T >( visited, target );
+}
+
+
+#endif // DMATTRIBUTE_H
diff --git a/sp/src/public/datamodel/dmattributetypes.h b/sp/src/public/datamodel/dmattributetypes.h
new file mode 100644
index 00000000..27880c28
--- /dev/null
+++ b/sp/src/public/datamodel/dmattributetypes.h
@@ -0,0 +1,316 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef DMATTRIBUTETYPES_H
+#define DMATTRIBUTETYPES_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier1/utlvector.h"
+#include "tier1/utlstring.h"
+#include "tier1/uniqueid.h"
+#include "Color.h"
+#include "mathlib/vector2d.h"
+#include "mathlib/vector.h"
+#include "mathlib/vector4d.h"
+#include "mathlib/vmatrix.h"
+#include "datamodel/dmelementhandle.h"
+#include "tier1/utlsymbol.h"
+
+
+//-----------------------------------------------------------------------------
+// Object Id
+//-----------------------------------------------------------------------------
+typedef UniqueId_t DmObjectId_t;
+
+
+//-----------------------------------------------------------------------------
+// Necessary for template specialization for AT_UNKNOWN
+//-----------------------------------------------------------------------------
+struct DmUnknownAttribute_t
+{
+ bool operator==( const DmUnknownAttribute_t& src ) const { return true; }
+};
+
+
+//-----------------------------------------------------------------------------
+// Element array
+//-----------------------------------------------------------------------------
+struct DmElementAttribute_t
+{
+ DmElementAttribute_t() : m_ElementType( UTL_INVAL_SYMBOL ) {}
+
+ operator DmElementHandle_t&() { return m_Handle; }
+ operator const DmElementHandle_t&() const { return m_Handle; }
+
+ DmElementHandle_t m_Handle;
+ UtlSymId_t m_ElementType;
+};
+
+struct DmElementArray_t : public CUtlVector< DmElementHandle_t >
+{
+ DmElementArray_t() : m_ElementType( UTL_INVAL_SYMBOL ) {}
+
+ UtlSymId_t m_ElementType;
+};
+
+
+//-----------------------------------------------------------------------------
+// Attribute chunk type enum
+//-----------------------------------------------------------------------------
+enum DmAttributeType_t
+{
+ AT_UNKNOWN = 0,
+
+ AT_FIRST_VALUE_TYPE,
+
+ AT_ELEMENT = AT_FIRST_VALUE_TYPE,
+ AT_INT,
+ AT_FLOAT,
+ AT_BOOL,
+ AT_STRING,
+ AT_VOID,
+ AT_OBJECTID,
+ AT_COLOR, //rgba
+ AT_VECTOR2,
+ AT_VECTOR3,
+ AT_VECTOR4,
+ AT_QANGLE,
+ AT_QUATERNION,
+ AT_VMATRIX,
+
+ AT_FIRST_ARRAY_TYPE,
+
+ AT_ELEMENT_ARRAY = AT_FIRST_ARRAY_TYPE,
+ AT_INT_ARRAY,
+ AT_FLOAT_ARRAY,
+ AT_BOOL_ARRAY,
+ AT_STRING_ARRAY,
+ AT_VOID_ARRAY,
+ AT_OBJECTID_ARRAY,
+ AT_COLOR_ARRAY,
+ AT_VECTOR2_ARRAY,
+ AT_VECTOR3_ARRAY,
+ AT_VECTOR4_ARRAY,
+ AT_QANGLE_ARRAY,
+ AT_QUATERNION_ARRAY,
+ AT_VMATRIX_ARRAY,
+ AT_TYPE_COUNT,
+};
+
+const char *GetTypeString( DmAttributeType_t type );
+
+inline bool IsValueType( DmAttributeType_t type )
+{
+ return type >= AT_FIRST_VALUE_TYPE && type < AT_FIRST_ARRAY_TYPE;
+}
+
+inline bool IsArrayType( DmAttributeType_t type )
+{
+ return type >= AT_FIRST_ARRAY_TYPE && type < AT_TYPE_COUNT;
+}
+
+inline bool IsTopological( DmAttributeType_t type )
+{
+ return type == AT_ELEMENT || type == AT_ELEMENT_ARRAY;
+}
+
+inline DmAttributeType_t ValueTypeToArrayType( DmAttributeType_t type )
+{
+ Assert( IsValueType( type ) );
+ return ( DmAttributeType_t )( ( type - AT_FIRST_VALUE_TYPE ) + AT_FIRST_ARRAY_TYPE );
+}
+
+inline DmAttributeType_t ArrayTypeToValueType( DmAttributeType_t type )
+{
+ Assert( IsArrayType( type ) );
+ return ( DmAttributeType_t )( ( type - AT_FIRST_ARRAY_TYPE ) + AT_FIRST_VALUE_TYPE );
+}
+
+inline int NumComponents( DmAttributeType_t type )
+{
+ switch ( type )
+ {
+ case AT_BOOL:
+ case AT_INT:
+ case AT_FLOAT:
+ return 1;
+
+ case AT_VECTOR2:
+ return 2;
+
+ case AT_VECTOR3:
+ case AT_QANGLE:
+ return 3;
+
+ case AT_COLOR: //rgba
+ case AT_VECTOR4:
+ case AT_QUATERNION:
+ return 4;
+
+ case AT_VMATRIX:
+ return 16;
+
+ case AT_ELEMENT:
+ case AT_STRING:
+ case AT_VOID:
+ case AT_OBJECTID:
+ default:
+ return 0;
+ }
+}
+
+template< typename T >
+inline float GetComponent( const T &value, int i )
+{
+ Assert( 0 );
+ return 0.0f;
+}
+
+template <> inline float GetComponent( const bool &value, int i )
+{
+ Assert( i == 0 );
+ return value ? 1.0f : 0.0f;
+}
+
+template <> inline float GetComponent( const int &value, int i )
+{
+ Assert( i == 0 );
+ return float( value );
+}
+
+template <> inline float GetComponent( const float &value, int i )
+{
+ Assert( i == 0 );
+ return value;
+}
+
+template <> inline float GetComponent( const Vector2D &value, int i )
+{
+ return value[ i ];
+}
+
+template <> inline float GetComponent( const Vector &value, int i )
+{
+ return value[ i ];
+}
+
+template <> inline float GetComponent( const QAngle &value, int i )
+{
+ return value[ i ];
+}
+
+template <> inline float GetComponent( const Color &value, int i )
+{
+ return value[ i ];
+}
+
+template <> inline float GetComponent( const Vector4D &value, int i )
+{
+ return value[ i ];
+}
+
+template <> inline float GetComponent( const Quaternion &value, int i )
+{
+ return value[ i ];
+}
+
+template <> inline float GetComponent( const VMatrix &value, int i )
+{
+ return value.Base()[ i ];
+}
+
+
+//-----------------------------------------------------------------------------
+// Attribute info...
+//-----------------------------------------------------------------------------
+template <typename T>
+class CDmAttributeInfo
+{
+public:
+ enum { ATTRIBUTE_TYPE = AT_UNKNOWN };
+
+ typedef T StorageType_t;
+
+ static DmAttributeType_t AttributeType()
+ {
+ return AT_UNKNOWN;
+ }
+
+ static const char *AttributeTypeName()
+ {
+ return "unknown";
+ }
+
+ static void SetDefaultValue( T& value )
+ {
+ Assert(0);
+ }
+};
+
+
+#define DECLARE_ATTRIBUTE_TYPE_INTERNAL( _className, _storageType, _attributeType, _attributeName, _defaultSetStatement ) \
+ template< > class CDmAttributeInfo< _className > \
+ { \
+ public: \
+ enum { ATTRIBUTE_TYPE = _attributeType }; \
+ typedef _storageType StorageType_t; \
+ static DmAttributeType_t AttributeType() { return _attributeType; } \
+ static const char *AttributeTypeName() { return _attributeName; } \
+ static void SetDefaultValue( _className& value ) { _defaultSetStatement } \
+ }; \
+
+#define DECLARE_ATTRIBUTE_ARRAY_TYPE_INTERNAL( _className, _storageType, _attributeType, _attributeName ) \
+ template< > class CDmAttributeInfo< CUtlVector<_className> > \
+ { \
+ public: \
+ enum { ATTRIBUTE_TYPE = _attributeType }; \
+ typedef _storageType StorageType_t; \
+ static DmAttributeType_t AttributeType() { return _attributeType; } \
+ static const char *AttributeTypeName() { return _attributeName; } \
+ static void SetDefaultValue( CUtlVector< _className >& value ) { value.RemoveAll(); } \
+ }; \
+
+#define DECLARE_ATTRIBUTE_TYPE( _className, _attributeType, _attributeName, _defaultSetStatement ) \
+ DECLARE_ATTRIBUTE_TYPE_INTERNAL( _className, _className, _attributeType, _attributeName, _defaultSetStatement )
+
+#define DECLARE_ATTRIBUTE_ARRAY_TYPE( _className, _attributeType, _attributeName )\
+ DECLARE_ATTRIBUTE_ARRAY_TYPE_INTERNAL( _className, CUtlVector< _className >, _attributeType, _attributeName )
+
+// NOTE: If you add an attribute type here, also add it to the list of DEFINE_ATTRIBUTE_TYPES in dmattribute.cpp
+DECLARE_ATTRIBUTE_TYPE( int, AT_INT, "int", value = 0; )
+DECLARE_ATTRIBUTE_TYPE( float, AT_FLOAT, "float", value = 0.0f; )
+DECLARE_ATTRIBUTE_TYPE( bool, AT_BOOL, "bool", value = false; )
+DECLARE_ATTRIBUTE_TYPE( Color, AT_COLOR, "color", value.SetColor( 0, 0, 0, 255 ); )
+DECLARE_ATTRIBUTE_TYPE( Vector2D, AT_VECTOR2, "vector2", value.Init( 0.0f, 0.0f ); )
+DECLARE_ATTRIBUTE_TYPE( Vector, AT_VECTOR3, "vector3", value.Init( 0.0f, 0.0f, 0.0f ); )
+DECLARE_ATTRIBUTE_TYPE( Vector4D, AT_VECTOR4, "vector4", value.Init( 0.0f, 0.0f, 0.0f, 0.0f ); )
+DECLARE_ATTRIBUTE_TYPE( QAngle, AT_QANGLE, "qangle", value.Init( 0.0f, 0.0f, 0.0f ); )
+DECLARE_ATTRIBUTE_TYPE( Quaternion, AT_QUATERNION, "quaternion", value.Init( 0.0f, 0.0f, 0.0f, 1.0f ); )
+DECLARE_ATTRIBUTE_TYPE( VMatrix, AT_VMATRIX, "matrix", MatrixSetIdentity( value ); )
+DECLARE_ATTRIBUTE_TYPE( CUtlString, AT_STRING, "string", value.Set( NULL ); )
+DECLARE_ATTRIBUTE_TYPE( CUtlBinaryBlock, AT_VOID, "binary", value.Set( NULL, 0 ); )
+DECLARE_ATTRIBUTE_TYPE( DmObjectId_t, AT_OBJECTID, "elementid", InvalidateUniqueId( &value ); )
+DECLARE_ATTRIBUTE_TYPE_INTERNAL( DmElementHandle_t, DmElementAttribute_t, AT_ELEMENT, "element", value = DMELEMENT_HANDLE_INVALID; )
+
+DECLARE_ATTRIBUTE_ARRAY_TYPE( int, AT_INT_ARRAY, "int_array" )
+DECLARE_ATTRIBUTE_ARRAY_TYPE( float, AT_FLOAT_ARRAY, "float_array" )
+DECLARE_ATTRIBUTE_ARRAY_TYPE( bool, AT_BOOL_ARRAY, "bool_array" )
+DECLARE_ATTRIBUTE_ARRAY_TYPE( Color, AT_COLOR_ARRAY, "color_array" )
+DECLARE_ATTRIBUTE_ARRAY_TYPE( Vector2D, AT_VECTOR2_ARRAY, "vector2_array" )
+DECLARE_ATTRIBUTE_ARRAY_TYPE( Vector, AT_VECTOR3_ARRAY, "vector3_array" )
+DECLARE_ATTRIBUTE_ARRAY_TYPE( Vector4D, AT_VECTOR4_ARRAY, "vector4_array" )
+DECLARE_ATTRIBUTE_ARRAY_TYPE( QAngle, AT_QANGLE_ARRAY, "qangle_array" )
+DECLARE_ATTRIBUTE_ARRAY_TYPE( Quaternion, AT_QUATERNION_ARRAY, "quaternion_array" )
+DECLARE_ATTRIBUTE_ARRAY_TYPE( VMatrix, AT_VMATRIX_ARRAY, "matrix_array" )
+DECLARE_ATTRIBUTE_ARRAY_TYPE( CUtlString, AT_STRING_ARRAY, "string_array" )
+DECLARE_ATTRIBUTE_ARRAY_TYPE( CUtlBinaryBlock, AT_VOID_ARRAY, "binary_array" )
+DECLARE_ATTRIBUTE_ARRAY_TYPE( DmObjectId_t, AT_OBJECTID_ARRAY, "elementid_array" )
+DECLARE_ATTRIBUTE_ARRAY_TYPE_INTERNAL( DmElementHandle_t, DmElementArray_t, AT_ELEMENT_ARRAY, "element_array" )
+
+
+#endif // DMATTRIBUTETYPES_H
diff --git a/sp/src/public/datamodel/dmattributevar.h b/sp/src/public/datamodel/dmattributevar.h
new file mode 100644
index 00000000..6c09a7c3
--- /dev/null
+++ b/sp/src/public/datamodel/dmattributevar.h
@@ -0,0 +1,1481 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef DMATTRIBUTEVAR_H
+#define DMATTRIBUTEVAR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier1/utlvector.h"
+#include "Color.h"
+#include "mathlib/vector2d.h"
+#include "mathlib/vector.h"
+#include "mathlib/vector4d.h"
+#include "mathlib/vmatrix.h"
+#include "datamodel/dmelement.h"
+#include "datamodel/dmattribute.h"
+
+template< class C, bool D > class CDmeHandle;
+
+//-----------------------------------------------------------------------------
+// Specialization for color
+//-----------------------------------------------------------------------------
+class CDmaColor : public CDmaVar< Color >
+{
+public:
+ // Set methods
+ void SetColor( int r, int g, int b, int a = 0 );
+ void SetRed( int r );
+ void SetGreen( int g );
+ void SetBlue( int b );
+ void SetAlpha( int a );
+
+ // Sets the color as a 32-bit integer
+ void SetRawColor( int color );
+
+ // Get methods
+ unsigned char r() const;
+ unsigned char g() const;
+ unsigned char b() const;
+ unsigned char a() const;
+ const unsigned char &operator[]( int index ) const;
+};
+
+
+//-----------------------------------------------------------------------------
+// Specialization for object ids
+//-----------------------------------------------------------------------------
+class CDmaObjectId : public CDmaVar< DmObjectId_t >
+{
+public:
+ void CreateObjectId( );
+ void Invalidate( );
+ bool IsValid( ) const;
+ bool IsEqual( const DmObjectId_t &id ) const;
+ const DmObjectId_t &operator=( const DmObjectId_t& src );
+ const CDmaObjectId& operator=( const CDmaObjectId& src );
+ const DmObjectId_t& Set( const DmObjectId_t &src );
+};
+
+
+//-----------------------------------------------------------------------------
+// Specialization for binary block
+//-----------------------------------------------------------------------------
+class CDmaBinaryBlock : public CDmaVar< CUtlBinaryBlock >
+{
+public:
+ void Get( void *pValue, int nMaxLen ) const;
+ void Set( const void *pValue, int nLen );
+ const void *Get() const;
+ const unsigned char& operator[]( int i ) const;
+
+ // Returns buffer length
+ int Length() const;
+};
+
+
+//-----------------------------------------------------------------------------
+// Specialization for elements
+//-----------------------------------------------------------------------------
+template <class T>
+class CDmaElement : public CDmaVar< DmElementHandle_t >
+{
+ typedef CDmaVar< DmElementHandle_t > BaseClass;
+
+public:
+ // Used to initialize the attribute in an element's OnConstruction method
+ void InitAndCreate( CDmElement *pOwner, const char *pAttributeName, const char *pElementName = NULL, int flags = 0 );
+ void Init( CDmElement *pOwner, const char *pAttributeName, int flags = 0 );
+
+ // Returns the type of elements allowed into this attribute. UTL_INVAL_SYMBOL allows everything.
+ UtlSymId_t GetElementType() const;
+
+ // Get/set
+ void Set( T* pElement );
+ T* GetElement() const;
+
+ // Cast
+ T* operator->() const;
+ operator T*() const;
+
+ // NULL check
+ bool operator!() const;
+
+ // Assignment.. wish I knew how to un-inline these methods
+ template <class S> CDmaElement<T> &operator=( S* pElement )
+ {
+ Set( static_cast<T*>( pElement ) );
+ return *this;
+ }
+
+ template <class S> CDmaElement<T> &operator=( const CDmaElement<S>& src )
+ {
+ Set( static_cast<T*>( src.Get() ) );
+ return *this;
+ }
+
+ template <class S> bool operator==( const CDmaElement<S>& src ) const
+ {
+ return Value() == src.Value();
+ }
+
+ template <class S> bool operator!=( const CDmaElement<S>& src ) const
+ {
+ return Value() != src.Value();
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+// Can access any array attribute, regardless of type
+// See below for type-specific array accessors which have more features
+//-----------------------------------------------------------------------------
+class CDmrGenericArrayConst
+{
+public:
+ CDmrGenericArrayConst( const CDmAttribute* pAttribute );
+ CDmrGenericArrayConst( const CDmElement *pElement, const char *pAttributeName );
+
+ // Array count
+ int Count() const;
+
+ // Gets
+ const void* GetUntyped( int i ) const;
+
+ // String conversion
+ const char* GetAsString( int i, char *pBuffer, size_t nBufLen ) const;
+
+ const CDmAttribute *GetAttribute() const;
+ bool IsValid() const;
+
+protected:
+ CDmrGenericArrayConst();
+ void Init( const CDmAttribute *pAttribute );
+ void Init( const CDmElement *pElement, const char *pAttributeName );
+
+ CDmAttribute *m_pAttribute;
+};
+
+class CDmrGenericArray : public CDmrGenericArrayConst
+{
+public:
+ CDmrGenericArray( CDmAttribute* pAttribute );
+ CDmrGenericArray( CDmElement *pElement, const char *pAttributeName );
+
+ void EnsureCount( int num );
+
+ // Sets multiple elements at the same time
+ int AddToTail();
+ void Remove( int elem ); // preserves order, shifts elements
+ void RemoveAll(); // doesn't deallocate memory
+ void SetMultiple( int i, int nCount, DmAttributeType_t valueType, const void *pValue );
+ void Set( int i, DmAttributeType_t valueType, const void *pValue );
+
+ // String conversion
+ void SetFromString( int i, const char *pValue );
+
+ CDmAttribute *GetAttribute();
+ const CDmAttribute *GetAttribute() const;
+};
+
+
+//-----------------------------------------------------------------------------
+// Helper template for external array attribute vars
+// NOTE: To use this class, don't use CDmaArrayBase directly. Instead, use
+// CDmaArray<T> var; <- Instantiate an array attribute var as a member of a element class
+// CDmrArray<T> var; <- Used to reference an existing array attribute + read/modify it
+// CDmrArrayConst<T> var; <- Used to reference an existing array attribute + read it (no modify)
+//
+// Also, there is a CDmaStringArray/CDmrStringArray/CDmrStringArrayConst for strings
+// and a CDmaElementArray/CDmrElementArray/CDmrElementArrayConst for elements
+//-----------------------------------------------------------------------------
+template< class T, class B >
+class CDmaArrayConstBase : public B
+{
+public:
+ // Accessors
+ const CUtlVector<T> &Get() const;
+ const T *Base() const;
+
+ // Iteration
+ int Count() const;
+ const T& operator[]( int i ) const;
+ const T& Element( int i ) const;
+ const T& Get( int i ) const;
+ const void* GetUntyped( int i ) const;
+ bool IsValidIndex( int i ) const;
+ int InvalidIndex( void ) const;
+
+ // Search
+ int Find( const T &value ) const;
+
+ // Attribute-related methods
+ const CDmAttribute *GetAttribute() const;
+ CDmElement *GetOwner();
+ bool IsDirty() const;
+
+protected:
+ CDmaArrayConstBase( );
+
+ CDmAttribute *m_pAttribute;
+};
+
+template< class T, class B >
+class CDmaArrayBase : public CDmaArrayConstBase< T, B >
+{
+public:
+ // Insertion
+ int AddToTail();
+ int InsertBefore( int elem );
+ int AddToTail( const T& src );
+ int InsertBefore( int elem, const T& src );
+ int AddMultipleToTail( int num );
+ int InsertMultipleBefore( int elem, int num );
+ void EnsureCount( int num );
+
+ // Element Modification
+ void Set( int i, const T& value );
+ void SetMultiple( int i, int nCount, const T* pValue );
+ void Swap( int i, int j );
+
+ // Copy related methods
+ void CopyArray( const T *pArray, int size );
+
+ // this is basically just a faster version of CopyArray which uses pointer swap
+ // NOTE: This doesn't work for element arrays
+ void SwapArray( CUtlVector< T > &array );
+
+ // Removal
+ void FastRemove( int elem );
+ void Remove( int elem );
+ void RemoveMultiple( int elem, int num );
+ void RemoveAll();
+
+ // Memory management
+ void EnsureCapacity( int num );
+ void Purge();
+
+ // Attribute-related methods
+ CDmAttribute *GetAttribute();
+ const CDmAttribute *GetAttribute() const;
+};
+
+
+//-----------------------------------------------------------------------------
+// Specialization for string arrays
+// NOTE: To use this class, don't use CDmaStringArrayBase directly. Instead, use
+// CDmaStringArray var; <- Instantiate an array attribute var as a member of a element class
+// CDmrStringArray var; <- Used to reference an existing array attribute + read/modify it
+// CDmrStringArrayConst var; <- Used to reference an existing array attribute + read it (no modify)
+//-----------------------------------------------------------------------------
+template< class BaseClass >
+class CDmaStringArrayConstBase : public BaseClass
+{
+public:
+ const char *operator[]( int i ) const;
+ const char *Element( int i ) const;
+ const char *Get( int i ) const;
+ const CUtlVector< CUtlString > &Get() const;
+
+ // Returns strlen of element i
+ int Length( int i ) const;
+};
+
+template< class B >
+class CDmaStringArrayBase : public CDmaStringArrayConstBase< CDmaArrayBase< CUtlString, B > >
+{
+ typedef CDmaStringArrayConstBase< CDmaArrayBase< CUtlString, B > > BaseClass;
+
+public:
+ // Sets an element in the array
+ void Set( int i, const char * pValue );
+
+ // Adds an element, uses copy constructor
+ int AddToTail( const char *pValue );
+ int InsertBefore( int elem, const char *pValue );
+};
+
+
+//-----------------------------------------------------------------------------
+// Specialization for elements
+// NOTE: To use this class, don't use CDmaElementArrayBase directly. Instead, use
+// CDmaElementArray< element_type > var; <- Instantiate an array attribute var as a member of a element class
+// CDmrElementArray< element_type > var; <- Used to reference an existing array attribute + read/modify it
+// CDmrElementArrayConst< element_type > var; <- Used to reference an existing array attribute + read it (no modify)
+//-----------------------------------------------------------------------------
+template< class E, class BaseClass >
+class CDmaElementArrayConstBase : public BaseClass
+{
+public:
+ // Returns the element type
+ UtlSymId_t GetElementType() const;
+
+ // Array access
+ E *operator[]( int i ) const;
+ E *Element( int i ) const;
+ E *Get( int i ) const;
+ const DmElementHandle_t& GetHandle( int i ) const;
+ const CUtlVector< DmElementHandle_t > &Get() const;
+
+ // Search
+ int Find( const E *pValue ) const;
+ int Find( DmElementHandle_t h ) const;
+};
+
+template < class E, class B >
+class CDmaElementArrayBase : public CDmaElementArrayConstBase< E, CDmaArrayBase< DmElementHandle_t, B > >
+{
+ typedef CDmaElementArrayConstBase< E, CDmaArrayBase< DmElementHandle_t, B > > BaseClass;
+
+public:
+ void SetHandle( int i, DmElementHandle_t h );
+ void Set( int i, E *pElement );
+
+ // Insertion
+ int AddToTail( );
+ int AddToTail( DmElementHandle_t src );
+ int AddToTail( E *pValue );
+ int InsertBefore( int elem );
+ int InsertBefore( int elem, DmElementHandle_t src );
+ int InsertBefore( int elem, E *pValue );
+
+ template< class C, bool D > int AddToTail( const CDmeHandle<C,D>& value )
+ {
+ return BaseClass::AddToTail( value.GetHandle() );
+ }
+
+ template< class C, bool D > int InsertBefore( int elem, const CDmeHandle<C,D>& value )
+ {
+ return BaseClass::InsertBefore( elem, value.GetHandle() );
+ }
+};
+
+
+// NOTE: The next couple classes are implementation details used to create CDmrAray/CDmaArray
+
+//-----------------------------------------------------------------------------
+// Base classes that contain data or refer to it; used for array accessor classes
+//-----------------------------------------------------------------------------
+template< typename T >
+class CDmaDataInternal
+{
+protected:
+ typedef typename CDmAttributeInfo< T >::StorageType_t D;
+
+ const T& Value() const { return m_Storage; }
+ T& Value( ) { return m_Storage; }
+ const D& Data() const { return m_Storage; }
+ D& Data( ) { return m_Storage; }
+
+private:
+ D m_Storage;
+};
+
+template< typename T >
+class CDmaDataExternal
+{
+protected:
+ typedef typename CDmAttributeInfo< T >::StorageType_t D;
+
+ CDmaDataExternal() : m_pStorage(0) {}
+ void Attach( void *pData ) { m_pStorage = (D*)pData; }
+ const T& Value() const { return *m_pStorage; }
+ T& Value( ) { return *m_pStorage; }
+ const D& Data() const { return *m_pStorage; }
+ D& Data( ) { return *m_pStorage; }
+
+private:
+ D* m_pStorage;
+};
+
+
+//-----------------------------------------------------------------------------
+// Versions for access, or for attribute vars
+//-----------------------------------------------------------------------------
+template< class T, class B >
+class CDmaDecorator : public B
+{
+public:
+ void Init( CDmElement *pOwner, const char *pAttributeName, int flags = 0 );
+};
+
+
+template< class T, class BaseClass >
+class CDmrDecoratorConst : public BaseClass
+{
+public:
+ void Init( const CDmAttribute* pAttribute );
+ void Init( const CDmElement *pElement, const char *pAttributeName );
+
+ bool IsValid() const;
+};
+
+template< class T, class BaseClass >
+class CDmrDecorator : public BaseClass
+{
+public:
+ void Init( CDmAttribute* pAttribute );
+ void Init( CDmElement *pElement, const char *pAttributeName, bool bAddAttribute = false );
+
+ bool IsValid() const;
+};
+
+
+#define DECLARE_ATTRIBUTE_ARRAY_VARIABLE( _className, _elementType ) \
+ public: \
+ _className() {}
+
+#define DECLARE_ATTRIBUTE_ARRAY_REFERENCE( _className, _elementType ) \
+ public: \
+ _className() {} \
+ _className( CDmAttribute* pAttribute ) { BaseClass::Init( pAttribute ); } \
+ _className( CDmElement *pElement, const char *pAttributeName, bool bAddAttribute = false ) { BaseClass::Init( pElement, pAttributeName, bAddAttribute ); } \
+ _className( CDmaArray<_className>& var ) { BaseClass::Init( var.GetAttribute() ); } \
+ _className( CDmrArray<_className>& var ) { BaseClass::Init( var.GetAttribute() ); }
+
+#define DECLARE_ATTRIBUTE_ARRAY_CONST_REFERENCE( _className, _elementType ) \
+ public: \
+ _className() {} \
+ _className( const CDmAttribute* pAttribute ) { BaseClass::Init( pAttribute ); } \
+ _className( const CDmElement *pElement, const char *pAttributeName ) { BaseClass::Init( pElement, pAttributeName ); } \
+ _className( const CDmaArray<_className>& var ) { BaseClass::Init( var.GetAttribute() ); } \
+ _className( const CDmrArrayConst<_className>& var ) { BaseClass::Init( var.GetAttribute() ); } \
+ _className( const CDmrArray<_className>& var ) { BaseClass::Init( var.GetAttribute() ); }
+
+template<class T> class CDmrArray;
+template<class T> class CDmrArrayConst;
+template<class T> class CDmaArray;
+
+//-----------------------------------------------------------------------------
+// Versions for access, or for attribute vars
+//-----------------------------------------------------------------------------
+template<class T>
+class CDmaArray : public CDmaDecorator< T, CDmaArrayBase< T, CDmaDataInternal< CUtlVector< T > > > >
+{
+ DECLARE_ATTRIBUTE_ARRAY_VARIABLE( CDmaArray, T );
+
+public:
+ const CDmaArray<T>& operator=( const CDmaArray<T> &val )
+ {
+ CopyArray( val.Base(), val.Count() );
+ return *this;
+ }
+
+ template< class C > const CDmaArray<T>& operator=( const C &val )
+ {
+ CopyArray( val.Base(), val.Count() );
+ return *this;
+ }
+
+private:
+ CDmaArray( const CDmaArray& array ) {}
+};
+
+
+template<class T>
+class CDmrArrayConst : public CDmrDecoratorConst< T, CDmaArrayConstBase< T, CDmaDataExternal< CUtlVector< T > > > >
+{
+ typedef CDmrDecoratorConst< T, CDmaArrayConstBase< T, CDmaDataExternal< CUtlVector< T > > > > BaseClass;
+ DECLARE_ATTRIBUTE_ARRAY_CONST_REFERENCE( CDmrArrayConst, T );
+};
+
+
+template<class T>
+class CDmrArray : public CDmrDecorator< T, CDmaArrayBase< T, CDmaDataExternal< CUtlVector< T > > > >
+{
+ typedef CDmrDecorator< T, CDmaArrayBase< T, CDmaDataExternal< CUtlVector< T > > > > BaseClass;
+ DECLARE_ATTRIBUTE_ARRAY_REFERENCE( CDmrArray, T );
+
+public:
+ const CDmrArray<T>& operator=( const CDmrArray<T> &val )
+ {
+ CopyArray( val.Base(), val.Count() );
+ return *this;
+ }
+
+ template< class C > const CDmrArray<T>& operator=( const C &val )
+ {
+ CopyArray( val.Base(), val.Count() );
+ return *this;
+ }
+};
+
+class CDmrStringArray;
+
+class CDmaStringArray : public CDmaDecorator< CUtlString, CDmaStringArrayBase< CDmaDataInternal< CUtlVector< CUtlString > > > >
+{
+ DECLARE_ATTRIBUTE_ARRAY_VARIABLE( CDmaStringArray, CUtlString );
+
+public:
+ const CDmaStringArray& operator=( const CDmaStringArray &val )
+ {
+ CopyArray( val.Base(), val.Count() );
+ return *this;
+ }
+
+ template< class C > const CDmaStringArray& operator=( const C &val )
+ {
+ CopyArray( val.Base(), val.Count() );
+ return *this;
+ }
+
+private:
+ CDmaStringArray( const CDmaStringArray& array ) {}
+};
+
+class CDmrStringArray : public CDmrDecorator< CUtlString, CDmaStringArrayBase< CDmaDataExternal< CUtlVector< CUtlString > > > >
+{
+ typedef CDmrDecorator< CUtlString, CDmaStringArrayBase< CDmaDataExternal< CUtlVector< CUtlString > > > > BaseClass;
+ DECLARE_ATTRIBUTE_ARRAY_REFERENCE( CDmrStringArray, CUtlString );
+
+public:
+ CDmrStringArray( CDmaStringArray& var ) { Init( var.GetAttribute() ); }
+ CDmrStringArray( CDmrStringArray& var ) { Init( var.GetAttribute() ); }
+
+ const CDmrStringArray& operator=( const CDmrStringArray &val )
+ {
+ CopyArray( val.Base(), val.Count() );
+ return *this;
+ }
+
+ template< class C > const CDmrStringArray& operator=( const C &val )
+ {
+ CopyArray( val.Base(), val.Count() );
+ return *this;
+ }
+};
+
+class CDmrStringArrayConst : public CDmrDecoratorConst< CUtlString, CDmaStringArrayConstBase< CDmaArrayConstBase< CUtlString, CDmaDataExternal< CUtlVector< CUtlString > > > > >
+{
+ typedef CDmrDecoratorConst< CUtlString, CDmaStringArrayConstBase< CDmaArrayConstBase< CUtlString, CDmaDataExternal< CUtlVector< CUtlString > > > > > BaseClass;
+ DECLARE_ATTRIBUTE_ARRAY_CONST_REFERENCE( CDmrStringArrayConst, CUtlString );
+
+public:
+ CDmrStringArrayConst( const CDmaStringArray& var ) { Init( var.GetAttribute() ); }
+ CDmrStringArrayConst( const CDmrStringArray& var ) { Init( var.GetAttribute() ); }
+ CDmrStringArrayConst( const CDmrStringArrayConst& var ) { Init( var.GetAttribute() ); }
+};
+
+
+//-----------------------------------------------------------------------------
+// Prevent CDmaArray for DmElementHandle_t
+//-----------------------------------------------------------------------------
+template<> class CDmaArray<DmElementHandle_t> { private: CDmaArray(); };
+
+
+template< class E > class CDmrElementArray;
+
+template< class E = CDmElement >
+class CDmaElementArray : public CDmaElementArrayBase< E, CDmaDataInternal< CUtlVector< DmElementHandle_t > > >
+{
+ DECLARE_ATTRIBUTE_ARRAY_VARIABLE( CDmaElementArray, DmElementHandle_t );
+
+public:
+ void Init( CDmElement *pOwner, const char *pAttributeName, int flags = 0 )
+ {
+ Assert( pOwner );
+ this->m_pAttribute = pOwner->AddExternalAttribute( pAttributeName, AT_ELEMENT_ARRAY, &CDmaElementArrayBase< E, CDmaDataInternal< CUtlVector< DmElementHandle_t > > >::Value() );
+ this->m_pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() );
+ if ( flags )
+ {
+ this->m_pAttribute->AddFlag( flags );
+ }
+ }
+
+ template< typename C > CDmaElementArray<E>& operator=( const C &val )
+ {
+ CopyArray( val.Base(), val.Count() );
+ return *this;
+ }
+
+ // NOTE: The copy operator= must be defined in addition to the generic one
+ const CDmaElementArray<E>& operator=( const CDmaElementArray<E> &val )
+ {
+ CopyArray( val.Base(), val.Count() );
+ return *this;
+ }
+
+private:
+ template< class C > CDmaElementArray( const CDmaElementArray<C>& var );
+};
+
+template< class E = CDmElement >
+class CDmrElementArrayConst : public CDmaElementArrayConstBase< E, CDmaArrayConstBase< DmElementHandle_t, CDmaDataExternal< CUtlVector< DmElementHandle_t > > > >
+{
+public:
+ CDmrElementArrayConst()
+ {
+ this->m_pAttribute = NULL;
+ }
+
+ CDmrElementArrayConst( const CDmAttribute* pAttribute )
+ {
+ Init( pAttribute );
+ }
+
+ CDmrElementArrayConst( const CDmElement *pElement, const char *pAttributeName )
+ {
+ Init( pElement, pAttributeName );
+ }
+
+ template< typename C > CDmrElementArrayConst( const CDmaElementArray<C>& var )
+ {
+ Init( var.GetAttribute() );
+ }
+
+ template< typename C > CDmrElementArrayConst( const CDmrElementArray<C>& var )
+ {
+ Init( var.GetAttribute() );
+ }
+
+ template< typename C > CDmrElementArrayConst( const CDmrElementArrayConst<C>& var )
+ {
+ Init( var.GetAttribute() );
+ }
+
+ void Init( const CDmAttribute* pAttribute )
+ {
+ if ( pAttribute && pAttribute->GetType() == AT_ELEMENT_ARRAY )
+ {
+ this->m_pAttribute = const_cast<CDmAttribute*>( pAttribute );
+ this->Attach( this->m_pAttribute->GetAttributeData() );
+ }
+ else
+ {
+ this->m_pAttribute = NULL;
+ this->Attach( NULL );
+ }
+ }
+
+ void Init( const CDmElement *pElement, const char *pAttributeName )
+ {
+ const CDmAttribute *pAttribute = NULL;
+ if ( pElement && pAttributeName && pAttributeName[0] )
+ {
+ pAttribute = (CDmAttribute*)pElement->GetAttribute( pAttributeName );
+ }
+ Init( pAttribute );
+ }
+
+ bool IsValid() const
+ {
+ return this->m_pAttribute != NULL;
+ }
+};
+
+template< class T = CDmElement >
+class CDmrElementArray : public CDmaElementArrayBase< T, CDmaDataExternal< CUtlVector< DmElementHandle_t > > >
+{
+public:
+ CDmrElementArray()
+ {
+ this->m_pAttribute = NULL;
+ }
+
+ CDmrElementArray( CDmAttribute* pAttribute )
+ {
+ Init( pAttribute );
+ }
+
+ CDmrElementArray( CDmElement *pElement, const char *pAttributeName, bool bAddAttribute = false )
+ {
+ Init( pElement, pAttributeName, bAddAttribute );
+ }
+
+ template< typename C > CDmrElementArray( CDmaElementArray<C>& var )
+ {
+ Init( var.GetAttribute() );
+ }
+
+ template< typename C > CDmrElementArray( CDmrElementArray<C>& var )
+ {
+ Init( var.GetAttribute() );
+ }
+
+ void Init( CDmAttribute* pAttribute )
+ {
+ if ( pAttribute && pAttribute->GetType() == AT_ELEMENT_ARRAY )
+ {
+ this->m_pAttribute = pAttribute;
+ this->Attach( this->m_pAttribute->GetAttributeData() );
+ }
+ else
+ {
+ this->m_pAttribute = NULL;
+ this->Attach( NULL );
+ }
+ }
+
+ void Init( CDmElement *pElement, const char *pAttributeName, bool bAddAttribute = false )
+ {
+ CDmAttribute *pAttribute = NULL;
+ if ( pElement && pAttributeName && pAttributeName[0] )
+ {
+ pAttribute = pElement->GetAttribute( pAttributeName );
+ if ( bAddAttribute && !pAttribute )
+ {
+ pAttribute = pElement->CreateAttribute( pAttributeName, AT_ELEMENT_ARRAY );
+
+ // FIXME: Should we do this?
+ pAttribute->SetElementTypeSymbol( T::GetStaticTypeSymbol() );
+ }
+ }
+ Init( pAttribute );
+ }
+
+ bool IsValid() const
+ {
+ return this->m_pAttribute != NULL;
+ }
+
+ template< typename C > CDmrElementArray<T>& operator=( const C &val )
+ {
+ CopyArray( val.Base(), val.Count() );
+ return *this;
+ }
+
+ // NOTE: The copy operator= must be defined in addition to the generic one
+ const CDmrElementArray<T>& operator=( const CDmrElementArray<T> &val )
+ {
+ CopyArray( val.Base(), val.Count() );
+ return *this;
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+//
+// Inline methods for CDmaVar
+//
+//-----------------------------------------------------------------------------
+template< class T > inline CDmaVar<T>::CDmaVar( )
+{
+ m_pAttribute = NULL;
+ CDmAttributeInfo<T>::SetDefaultValue( m_Storage );
+}
+
+template< class T > inline void CDmaVar<T>::Init( CDmElement *pOwner, const char *pAttributeName, int flags )
+{
+ Assert( pOwner );
+ m_pAttribute = pOwner->AddExternalAttribute( pAttributeName, CDmAttributeInfo<T>::AttributeType(), &m_Storage );
+ Assert( m_pAttribute );
+ if ( flags )
+ {
+ m_pAttribute->AddFlag( flags );
+ }
+}
+
+template< class T > inline void CDmaVar<T>::InitAndSet( CDmElement *pOwner, const char *pAttributeName, const T &value, int flags )
+{
+ Init( pOwner, pAttributeName );
+ Set( value );
+
+ // this has to happen AFTER set so the set happens before FATTRIB_READONLY
+ if ( flags )
+ {
+ m_pAttribute->AddFlag( flags );
+ }
+}
+
+template< class T > inline const T& CDmaVar<T>::Set( const T &val )
+{
+ Assert( m_pAttribute );
+ m_pAttribute->SetValue( val );
+ return m_Storage;
+}
+
+template< class T > inline const T& CDmaVar<T>::operator=( const T &val )
+{
+ return Set( val );
+}
+
+template< class T > inline const CDmaVar<T>& CDmaVar<T>::operator=( const CDmaVar<T>& src )
+{
+ Set( src.Get() );
+ return *this;
+}
+
+template< class T > inline const T& CDmaVar<T>::operator+=( const T &val )
+{
+ return Set( Value() + val );
+}
+
+template< class T > inline const T& CDmaVar<T>::operator-=( const T &val )
+{
+ return Set( Value() - val );
+}
+
+template< class T > inline const T& CDmaVar<T>::operator/=( const T &val )
+{
+ return Set( Value() / val );
+}
+
+template< class T > inline const T& CDmaVar<T>::operator*=( const T &val )
+{
+ return Set( Value() * val );
+}
+
+template< class T > inline const T& CDmaVar<T>::operator^=( const T &val )
+{
+ return Set( Value() ^ val );
+}
+
+template< class T > inline const T& CDmaVar<T>::operator|=( const T &val )
+{
+ return Set( Value() | val );
+}
+
+template< class T > inline const T& CDmaVar<T>::operator&=( const T &val )
+{
+ return Set( Value() & val );
+}
+
+template< class T > inline T CDmaVar<T>::operator++()
+{
+ return Set( Value() + 1 );
+}
+
+template< class T > inline T CDmaVar<T>::operator--()
+{
+ return Set( Value() - 1 );
+}
+
+template< class T > inline T CDmaVar<T>::operator++( int ) // postfix version..
+{
+ T oldValue = Value();
+ Set( Value() + 1 );
+ return oldValue;
+}
+
+template< class T > inline T CDmaVar<T>::operator--( int ) // postfix version..
+{
+ T oldValue = Value();
+ Set( Value() - 1 );
+ return oldValue;
+}
+
+template< class T > inline CDmaVar<T>::operator const T&() const
+{
+ return Value();
+}
+
+template< class T > inline const T& CDmaVar<T>::Get() const
+{
+ return Value();
+}
+
+template< class T > inline const T* CDmaVar<T>::operator->() const
+{
+ return &Value();
+}
+
+template< class T > inline CDmAttribute *CDmaVar<T>::GetAttribute()
+{
+ Assert( m_pAttribute );
+ return m_pAttribute;
+}
+
+template< class T > inline const CDmAttribute *CDmaVar<T>::GetAttribute() const
+{
+ Assert( m_pAttribute );
+ return m_pAttribute;
+}
+
+template< class T > inline bool CDmaVar<T>::IsDirty() const
+{
+ Assert( m_pAttribute );
+ return m_pAttribute->IsFlagSet( FATTRIB_DIRTY );
+}
+
+template< class T > inline const T& CDmaVar<T>::Value() const
+{
+ return m_Storage;
+}
+
+template< class T > inline T& CDmaVar<T>::Value()
+{
+ return m_Storage;
+}
+
+template<> inline const DmElementHandle_t& CDmaVar< DmElementHandle_t >::Value() const
+{
+ return m_Storage.m_Handle;
+}
+
+template<> inline DmElementHandle_t& CDmaVar< DmElementHandle_t >::Value()
+{
+ return m_Storage.m_Handle;
+}
+
+template< class T > inline const typename CDmaVar<T>::D& CDmaVar<T>::Storage() const
+{
+ return m_Storage;
+}
+
+template< class T > inline typename CDmaVar<T>::D& CDmaVar<T>::Storage()
+{
+ return m_Storage;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Inline methods for CDmaColor
+//
+//-----------------------------------------------------------------------------
+inline void CDmaColor::SetColor( int r, int g, int b, int a )
+{
+ Color clr( r, g, b, a );
+ m_pAttribute->SetValue( clr );
+}
+
+inline void CDmaColor::SetRed( int r )
+{
+ Color org = Value();
+ org[ 0 ] = r;
+ m_pAttribute->SetValue( org );
+}
+
+inline void CDmaColor::SetGreen( int g )
+{
+ Color org = Value();
+ org[ 1 ] = g;
+ m_pAttribute->SetValue( org );
+}
+
+inline void CDmaColor::SetBlue( int b )
+{
+ Color org = Value();
+ org[ 2 ] = b;
+ m_pAttribute->SetValue( org );
+}
+
+inline void CDmaColor::SetAlpha( int a )
+{
+ Color org = Value();
+ org[ 3 ] = a;
+ m_pAttribute->SetValue( org );
+}
+
+inline unsigned char CDmaColor::r() const
+{
+ return (unsigned char)Value().r();
+}
+
+inline unsigned char CDmaColor::g() const
+{
+ return (unsigned char)Value().g();
+}
+
+inline unsigned char CDmaColor::b() const
+{
+ return (unsigned char)Value().b();
+}
+
+inline unsigned char CDmaColor::a() const
+{
+ return (unsigned char)Value().a();
+}
+
+inline const unsigned char &CDmaColor::operator[](int index) const
+{
+ return Value()[index];
+}
+
+inline void CDmaColor::SetRawColor( int color )
+{
+ Color clr;
+ clr.SetRawColor( color );
+ m_pAttribute->SetValue( clr );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Inline methods for CDmaObjectId
+//
+//-----------------------------------------------------------------------------
+inline void CDmaObjectId::CreateObjectId( )
+{
+ DmObjectId_t id;
+ CreateUniqueId( &id );
+ m_pAttribute->SetValue( id );
+}
+
+inline void CDmaObjectId::Invalidate( )
+{
+ DmObjectId_t id;
+ InvalidateUniqueId( &id );
+ m_pAttribute->SetValue( id );
+}
+
+inline bool CDmaObjectId::IsValid( ) const
+{
+ return IsUniqueIdValid( Value() );
+}
+
+inline bool CDmaObjectId::IsEqual( const DmObjectId_t &id ) const
+{
+ return IsUniqueIdEqual( Value(), id );
+}
+
+inline const DmObjectId_t &CDmaObjectId::operator=( const DmObjectId_t& src )
+{
+ m_pAttribute->SetValue( src );
+ return Value();
+}
+
+inline const CDmaObjectId& CDmaObjectId::operator=( const CDmaObjectId& src )
+{
+ m_pAttribute->SetValue( src.Get() );
+ return *this;
+}
+
+inline const DmObjectId_t& CDmaObjectId::Set( const DmObjectId_t &src )
+{
+ m_pAttribute->SetValue( src );
+ return Value();
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Inline methods for CDmaString
+//
+//-----------------------------------------------------------------------------
+inline const char *CDmaString::Get( ) const
+{
+ return Value().Get();
+}
+
+inline CDmaString::operator const char*() const
+{
+ return Value().Get();
+}
+
+inline void CDmaString::Set( const char *pValue )
+{
+ CUtlString str( pValue, pValue ? Q_strlen( pValue ) + 1 : 0 );
+ m_pAttribute->SetValue( str );
+}
+
+// Returns strlen
+inline int CDmaString::Length() const
+{
+ return Value().Length();
+}
+
+inline CDmaString &CDmaString::operator=( const char *src )
+{
+ Set( src );
+ return *this;
+}
+
+inline const CDmaString& CDmaString::operator=( const CDmaString& src )
+{
+ Set( src.Get() );
+ return *this;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Inline methods for CDmaBinaryBlock
+//
+//-----------------------------------------------------------------------------
+inline void CDmaBinaryBlock::Get( void *pValue, int nMaxLen ) const
+{
+ Value().Get( pValue, nMaxLen );
+}
+
+inline void CDmaBinaryBlock::Set( const void *pValue, int nLen )
+{
+ CUtlBinaryBlock block( pValue, nLen );
+ m_pAttribute->SetValue( block );
+}
+
+inline const void *CDmaBinaryBlock::Get() const
+{
+ return Value().Get();
+}
+
+inline const unsigned char& CDmaBinaryBlock::operator[]( int i ) const
+{
+ return Value()[i];
+}
+
+inline int CDmaBinaryBlock::Length() const
+{
+ return Value().Length();
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Inline methods for CDmaElement
+//
+//-----------------------------------------------------------------------------
+template <class T>
+inline void CDmaElement<T>::InitAndCreate( CDmElement *pOwner, const char *pAttributeName, const char *pElementName, int flags )
+{
+ Init( pOwner, pAttributeName );
+
+ DmElementHandle_t hElement = DMELEMENT_HANDLE_INVALID;
+ if ( !g_pDataModel->IsUnserializing() )
+ {
+ hElement = g_pDataModel->CreateElement( T::GetStaticTypeSymbol(), pElementName, pOwner->GetFileId() );
+ }
+ Assert( m_pAttribute );
+ m_pAttribute->SetValue( hElement );
+
+ // this has to happen AFTER set so the set happens before FATTRIB_READONLY
+ m_pAttribute->AddFlag( flags | FATTRIB_MUSTCOPY );
+}
+
+template <class T>
+inline void CDmaElement<T>::Init( CDmElement *pOwner, const char *pAttributeName, int flags )
+{
+ BaseClass::Init( pOwner, pAttributeName );
+
+ Assert( m_pAttribute );
+ m_pAttribute->SetElementTypeSymbol( T::GetStaticTypeSymbol() );
+ if ( flags )
+ {
+ m_pAttribute->AddFlag( flags );
+ }
+}
+
+template <class T>
+inline UtlSymId_t CDmaElement<T>::GetElementType() const
+{
+ return this->Data().m_ElementType;
+}
+
+template <class T>
+inline T* CDmaElement<T>::GetElement() const
+{
+ CDmElement *pElement = g_pDataModel->GetElement( Value() );
+ Assert( !pElement || pElement->IsA( T::GetStaticTypeSymbol() ) );
+ return static_cast< T* >( pElement );
+}
+
+template <class T>
+inline T* CDmaElement<T>::operator->() const
+{
+ return GetElement();
+}
+
+template <class T>
+inline CDmaElement<T>::operator T*() const
+{
+ return GetElement();
+}
+
+template <class T>
+inline void CDmaElement<T>::Set( T* pElement )
+{
+ Assert( m_pAttribute );
+ m_pAttribute->SetValue( pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID );
+}
+
+template <class T>
+inline bool CDmaElement<T>::operator!() const
+{
+ return ( GetElement() == NULL );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Inline methods for CDmaArrayBase
+//
+//-----------------------------------------------------------------------------
+template< class T, class B >
+inline const CUtlVector<T>& CDmaArrayConstBase<T,B>::Get() const
+{
+ return this->Value();
+}
+
+template< class T, class B >
+inline const T *CDmaArrayConstBase<T,B>::Base() const
+{
+ return this->Value().Base();
+}
+
+template< class T, class B >
+inline const T& CDmaArrayConstBase<T,B>::operator[]( int i ) const
+{
+ return this->Value()[ i ];
+}
+
+template< class T, class B >
+const T& CDmaArrayConstBase<T,B>::Element( int i ) const
+{
+ return this->Value()[ i ];
+}
+
+template< class T, class B >
+inline const T& CDmaArrayConstBase<T,B>::Get( int i ) const
+{
+ return this->Value()[ i ];
+}
+
+template< class T, class B >
+const void* CDmaArrayConstBase<T,B>::GetUntyped( int i ) const
+{
+ return &( this->Value()[ i ] );
+}
+
+template< class T, class B >
+inline int CDmaArrayConstBase<T,B>::Count() const
+{
+ return this->Value().Count();
+}
+
+template< class T, class B >
+inline bool CDmaArrayConstBase<T,B>::IsValidIndex( int i ) const
+{
+ return this->Value().IsValidIndex( i );
+}
+
+template< class T, class B >
+inline int CDmaArrayConstBase<T,B>::InvalidIndex( void ) const
+{
+ return this->Value().InvalidIndex();
+}
+
+template< class T, class B >
+inline const CDmAttribute *CDmaArrayConstBase<T,B>::GetAttribute() const
+{
+ Assert( m_pAttribute );
+ return m_pAttribute;
+}
+
+template< class T, class B >
+inline CDmElement *CDmaArrayConstBase<T,B>::GetOwner()
+{
+ return m_pAttribute->GetOwner();
+}
+
+template< class T, class B >
+inline bool CDmaArrayConstBase<T,B>::IsDirty() const
+{
+ return m_pAttribute->IsFlagSet( FATTRIB_DIRTY );
+}
+
+
+template< class T, class B >
+inline CDmAttribute *CDmaArrayBase<T,B>::GetAttribute()
+{
+ Assert( this->m_pAttribute );
+ return this->m_pAttribute;
+}
+
+template< class T, class B >
+inline const CDmAttribute *CDmaArrayBase<T,B>::GetAttribute() const
+{
+ Assert( this->m_pAttribute );
+ return this->m_pAttribute;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Inline methods for CDmaStringArrayBase
+//
+//-----------------------------------------------------------------------------
+template< class B >
+inline const char *CDmaStringArrayConstBase<B>::operator[]( int i ) const
+{
+ return this->Value()[ i ].Get();
+}
+
+template< class B >
+inline const char *CDmaStringArrayConstBase<B>::Element( int i ) const
+{
+ return this->Value()[ i ].Get();
+}
+
+template< class B >
+inline const char *CDmaStringArrayConstBase<B>::Get( int i ) const
+{
+ return this->Value()[ i ].Get();
+}
+
+template< class B >
+inline const CUtlVector< CUtlString > &CDmaStringArrayConstBase<B>::Get() const
+{
+ return this->Value();
+}
+
+// Returns strlen of element i
+template< class B >
+inline int CDmaStringArrayConstBase<B>::Length( int i ) const
+{
+ return this->Value()[i].Length();
+}
+
+template< class B >
+inline void CDmaStringArrayBase<B>::Set( int i, const char * pValue )
+{
+ CUtlString str( pValue, Q_strlen( pValue ) + 1 );
+ BaseClass::Set( i, str );
+}
+
+// Adds an element, uses copy constructor
+template< class B >
+inline int CDmaStringArrayBase<B>::AddToTail( const char *pValue )
+{
+ CUtlString str( pValue, Q_strlen( pValue ) + 1 );
+ return BaseClass::AddToTail( str );
+}
+
+template< class B >
+inline int CDmaStringArrayBase<B>::InsertBefore( int elem, const char *pValue )
+{
+ CUtlString str( pValue, Q_strlen( pValue ) + 1 );
+ return BaseClass::InsertBefore( elem, str );
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// Inline methods for CDmaElementArrayBase
+//
+//-----------------------------------------------------------------------------
+template< class E, class B >
+inline UtlSymId_t CDmaElementArrayConstBase<E,B>::GetElementType() const
+{
+ return this->Data().m_ElementType;
+}
+
+template< class E, class B >
+inline E *CDmaElementArrayConstBase<E,B>::operator[]( int i ) const
+{
+ return GetElement<E>( this->Value()[i] );
+}
+
+template< class E, class B >
+inline E *CDmaElementArrayConstBase<E,B>::Element( int i ) const
+{
+ return GetElement<E>( this->Value()[i] );
+}
+
+template< class E, class B >
+inline E *CDmaElementArrayConstBase<E,B>::Get( int i ) const
+{
+ return GetElement<E>( this->Value()[i] );
+}
+
+template< class E, class B >
+inline const DmElementHandle_t& CDmaElementArrayConstBase<E,B>::GetHandle( int i ) const
+{
+ return this->Value()[i];
+}
+
+template< class E, class B >
+inline const CUtlVector< DmElementHandle_t > &CDmaElementArrayConstBase<E,B>::Get() const
+{
+ return this->Value();
+}
+
+// Search
+template< class E, class B >
+inline int CDmaElementArrayConstBase<E,B>::Find( const E *pValue ) const
+{
+ if ( !pValue )
+ return -1;
+ return B::Find( pValue->GetHandle() );
+}
+
+template< class E, class B >
+inline int CDmaElementArrayConstBase<E,B>::Find( DmElementHandle_t h ) const
+{
+ return B::Find( h );
+}
+
+template< class E, class B >
+inline void CDmaElementArrayBase<E,B>::SetHandle( int i, DmElementHandle_t h )
+{
+ BaseClass::Set( i, h );
+}
+
+template< class E, class B >
+inline void CDmaElementArrayBase<E,B>::Set( int i, E *pElement )
+{
+ BaseClass::Set( i, pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID );
+}
+
+// Adds an element, uses copy constructor
+template< class E, class B >
+inline int CDmaElementArrayBase<E,B>::AddToTail( )
+{
+ return BaseClass::AddToTail( );
+}
+
+template< class E, class B >
+inline int CDmaElementArrayBase<E,B>::AddToTail( E *pValue )
+{
+ return BaseClass::AddToTail( pValue ? pValue->GetHandle() : DMELEMENT_HANDLE_INVALID );
+}
+
+template< class E, class B >
+inline int CDmaElementArrayBase<E,B>::AddToTail( DmElementHandle_t src )
+{
+ return BaseClass::AddToTail( src );
+}
+
+template< class E, class B >
+inline int CDmaElementArrayBase<E,B>::InsertBefore( int elem )
+{
+ return BaseClass::InsertBefore( elem );
+}
+
+template< class E, class B >
+inline int CDmaElementArrayBase<E,B>::InsertBefore( int elem, E *pValue )
+{
+ return BaseClass::InsertBefore( elem, pValue ? pValue->GetHandle() : DMELEMENT_HANDLE_INVALID );
+}
+
+template< class E, class B >
+inline int CDmaElementArrayBase<E,B>::InsertBefore( int elem, DmElementHandle_t src )
+{
+ return BaseClass::InsertBefore( elem, src );
+}
+
+
+
+//-----------------------------------------------------------------------------
+//
+// Inline methods for CDmrGenericArray
+//
+//-----------------------------------------------------------------------------
+inline const CDmAttribute *CDmrGenericArrayConst::GetAttribute() const
+{
+ Assert( m_pAttribute );
+ return m_pAttribute;
+}
+
+inline bool CDmrGenericArrayConst::IsValid() const
+{
+ return m_pAttribute != NULL;
+}
+
+inline CDmAttribute *CDmrGenericArray::GetAttribute()
+{
+ Assert( m_pAttribute );
+ return m_pAttribute;
+}
+
+inline const CDmAttribute *CDmrGenericArray::GetAttribute() const
+{
+ Assert( m_pAttribute );
+ return m_pAttribute;
+}
+
+
+#endif // DMATTRIBUTEVAR_H
diff --git a/sp/src/public/datamodel/dmehandle.h b/sp/src/public/datamodel/dmehandle.h
new file mode 100644
index 00000000..0353aeb9
--- /dev/null
+++ b/sp/src/public/datamodel/dmehandle.h
@@ -0,0 +1,243 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// The copyright to the contents herein is the property of Valve, L.L.C.
+// The contents may be used and/or copied only with the written permission of
+// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
+// the agreement/contract under which the contents have been supplied.
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+
+#ifndef DMEHANDLE_H
+#define DMEHANDLE_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include "datamodel/idatamodel.h"
+#include "datamodel/dmelement.h"
+#include "datamodel/dmattribute.h"
+#include "datamodel/dmattributevar.h"
+
+
+//-----------------------------------------------------------------------------
+// Purpose: CDmeHandle is a templatized wrapper around DmElementHandle_t
+//-----------------------------------------------------------------------------
+template< class DmeType, bool Counted = false >
+class CDmeHandle : public CDmeElementRefHelper
+{
+public:
+ CDmeHandle() : m_handle( DMELEMENT_HANDLE_INVALID )
+ {
+ }
+
+ explicit CDmeHandle( CDmElement *pObject ) : m_handle( DMELEMENT_HANDLE_INVALID )
+ {
+ Set( pObject );
+ }
+
+ CDmeHandle( DmElementHandle_t h ) : m_handle( DMELEMENT_HANDLE_INVALID )
+ {
+ Set( h );
+ }
+
+ CDmeHandle( const CDmeHandle< DmeType, Counted > &handle ) : m_handle( DMELEMENT_HANDLE_INVALID )
+ {
+ Set( handle.m_handle );
+ }
+
+ template < class T, bool B >
+ CDmeHandle( const CDmeHandle< T, B > &handle ) : m_handle( DMELEMENT_HANDLE_INVALID )
+ {
+ DmeType *p = ( T* )NULL; // triggers compiler error if converting from invalid handle type
+ NOTE_UNUSED( p );
+
+ Set( handle.GetHandle() );
+ }
+
+ ~CDmeHandle()
+ {
+ if ( !g_pDataModel )
+ return; // some handles are static, and don't get destroyed until program termination
+
+ Unref( m_handle, Counted );
+ }
+
+ template < class T, bool B >
+ CDmeHandle& operator=( const CDmeHandle< T, B > &handle )
+ {
+ DmeType *p = ( T* )NULL; // triggers compiler error if converting from invalid handle type
+ NOTE_UNUSED( p );
+
+ Set( handle.GetHandle() );
+ return *this;
+ }
+
+ DmeType *Get()
+ {
+ return static_cast< DmeType* >( g_pDataModel->GetElement( m_handle ) );
+ }
+
+ const DmeType *Get() const
+ {
+ return static_cast< DmeType* >( g_pDataModel->GetElement( m_handle ) );
+ }
+
+ DmElementHandle_t GetHandle() const
+ {
+ return m_handle;
+ }
+
+ void Set( CDmElement *pObject )
+ {
+ Set( pObject ? pObject->GetHandle() : DMELEMENT_HANDLE_INVALID );
+ }
+
+ void Set( DmElementHandle_t h )
+ {
+ if ( h == m_handle )
+ return;
+
+ Unref( m_handle, Counted );
+
+ m_handle = h;
+ if ( h != DMELEMENT_HANDLE_INVALID )
+ {
+ CDmElement *pElement = g_pDataModel->GetElement( m_handle );
+ Assert( pElement );
+ if ( pElement && !pElement->IsA( DmeType::GetStaticTypeSymbol() ) )
+ {
+ m_handle = DMELEMENT_HANDLE_INVALID;
+ }
+ }
+
+ Ref( m_handle, Counted );
+ }
+
+ operator DmeType*()
+ {
+ return Get();
+ }
+
+ operator const DmeType*() const
+ {
+ return Get();
+ }
+
+ operator DmElementHandle_t() const
+ {
+ return m_handle;
+ }
+
+ DmeType* operator->()
+ {
+ return Get();
+ }
+
+ const DmeType* operator->() const
+ {
+ return Get();
+ }
+
+ CDmeHandle& operator=( DmElementHandle_t h )
+ {
+ Set( h );
+ return *this;
+ }
+
+ CDmeHandle& operator=( CDmElement *pObject )
+ {
+ Set( pObject );
+ return *this;
+ }
+
+ bool operator==( const CDmeHandle< DmeType > &h ) const
+ {
+ return m_handle == h.m_handle;
+ }
+
+ bool operator!=( const CDmeHandle< DmeType > &h ) const
+ {
+ return !operator==( h );
+ }
+
+ bool operator<( const CDmeHandle< DmeType > &h ) const
+ {
+ return m_handle < h.m_handle;
+ }
+
+ bool operator==( DmeType *pObject ) const
+ {
+ DmElementHandle_t h = pObject ? pObject->GetHandle() : DMELEMENT_HANDLE_INVALID;
+ return m_handle == h;
+ }
+
+ bool operator!=( DmeType *pObject ) const
+ {
+ return !operator==( pObject );
+ }
+
+ bool operator==( DmElementHandle_t h ) const
+ {
+ return ( m_handle == h );
+ }
+
+ bool operator!=( DmElementHandle_t h ) const
+ {
+ return ( m_handle != h );
+ }
+
+ operator bool() const
+ {
+ return ( Get() != NULL );
+ }
+
+ bool operator!() const
+ {
+ return ( Get() == NULL );
+ }
+
+private:
+ DmElementHandle_t m_handle;
+};
+
+typedef CDmeHandle< CDmElement, true > CDmeCountedHandle;
+
+
+//-----------------------------------------------------------------------------
+// Vector of element handles
+//-----------------------------------------------------------------------------
+typedef CUtlVector< CDmeHandle<CDmElement> > DmeHandleVec_t;
+
+
+
+//-----------------------------------------------------------------------------
+// helper class for undo classes to allow them to hold onto refcounted element handles
+//-----------------------------------------------------------------------------
+
+template< typename T >
+class CDmAttributeUndoStorageType
+{
+public:
+ typedef T UndoStorageType;
+};
+
+template<>
+class CDmAttributeUndoStorageType< DmElementHandle_t >
+{
+public:
+ typedef CDmeCountedHandle UndoStorageType;
+};
+
+template<>
+class CDmAttributeUndoStorageType< CUtlVector< DmElementHandle_t > >
+{
+public:
+ typedef CUtlVector< CDmeCountedHandle > UndoStorageType;
+};
+
+#endif // DMEHANDLE_H
diff --git a/sp/src/public/datamodel/dmelement.h b/sp/src/public/datamodel/dmelement.h
new file mode 100644
index 00000000..9048f350
--- /dev/null
+++ b/sp/src/public/datamodel/dmelement.h
@@ -0,0 +1,618 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef DMELEMENT_H
+#define DMELEMENT_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier1/utlmap.h"
+#include "tier1/utlhash.h"
+#include "tier1/utlvector.h"
+#include "tier1/utlsymbol.h"
+#include "datamodel/attributeflags.h"
+#include "datamodel/idatamodel.h"
+#include "datamodel/dmvar.h"
+
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+typedef bool (CDmElement::*pfnCommandMethod)( const char *command, const char *args );
+
+// element/element array traversal path item - assumes the full path does NOT contain cycles
+struct ElementPathItem_t
+{
+ ElementPathItem_t( DmElementHandle_t hElem = DMELEMENT_HANDLE_INVALID,
+ DmAttributeHandle_t hAttr = DMATTRIBUTE_HANDLE_INVALID,
+ int idx = -1 )
+ : hElement( hElem ), hAttribute( hAttr ), nIndex( idx )
+ {
+ }
+
+ // only uses hElement so that it can be used to search for elements
+ bool operator==( const ElementPathItem_t &that ) const
+ {
+ return hElement == that.hElement;
+ }
+
+ DmElementHandle_t hElement;
+ DmAttributeHandle_t hAttribute;
+ int nIndex;
+};
+
+
+//-----------------------------------------------------------------------------
+// singly-linked attribute list
+//-----------------------------------------------------------------------------
+struct DmAttributeList_t
+{
+ DmAttributeList_t() : m_hAttribute( DMATTRIBUTE_HANDLE_INVALID ), m_pNext( NULL ) {}
+ DmAttributeHandle_t m_hAttribute;
+ DmAttributeList_t *m_pNext;
+};
+
+//-----------------------------------------------------------------------------
+// helper class to allow CDmeHandle access to g_pDataModelImp
+//-----------------------------------------------------------------------------
+class CDmeElementRefHelper
+{
+protected:
+ void Ref ( DmElementHandle_t hElement, bool bStrong );
+ void Unref( DmElementHandle_t hElement, bool bStrong );
+};
+
+//-----------------------------------------------------------------------------
+// element reference struct - containing attribute referrers and handle refcount
+//-----------------------------------------------------------------------------
+struct DmElementReference_t
+{
+ explicit DmElementReference_t( DmElementHandle_t hElement = DMELEMENT_HANDLE_INVALID ) :
+ m_hElement( hElement ), m_nWeakHandleCount( 0 ), m_nStrongHandleCount( 0 )
+ {
+ }
+ DmElementReference_t( const DmElementReference_t &that ) :
+ m_hElement( that.m_hElement ), m_nWeakHandleCount( that.m_nWeakHandleCount ),
+ m_nStrongHandleCount( that.m_nStrongHandleCount ), m_attributes( that.m_attributes )
+ {
+ }
+ DmElementReference_t &operator=( const DmElementReference_t &that )
+ {
+ m_hElement = that.m_hElement;
+ m_nWeakHandleCount = that.m_nWeakHandleCount;
+ m_nStrongHandleCount = that.m_nStrongHandleCount;
+ m_attributes.m_hAttribute = that.m_attributes.m_hAttribute;
+ m_attributes.m_pNext = that.m_attributes.m_pNext;
+ return *this;
+ }
+ ~DmElementReference_t()
+ {
+ // Assert( !IsStronglyReferenced() );
+ }
+
+ void AddAttribute( CDmAttribute *pAttribute );
+ void RemoveAttribute( CDmAttribute *pAttribute );
+
+ bool IsStronglyReferenced() // should this element be kept around (even if it's DmElementHandle_t is invalidated)
+ {
+ return m_attributes.m_hAttribute != DMATTRIBUTE_HANDLE_INVALID || m_nStrongHandleCount > 0;
+ }
+
+ bool IsWeaklyReferenced() // should we keep this element's DmElementHandle_t mapped to it's id (even if the element is deleted)
+ {
+ return IsStronglyReferenced() || m_nWeakHandleCount > 0;
+ }
+
+ int EstimateMemoryOverhead()
+ {
+ int nBytes = 0;
+ for ( DmAttributeList_t *pLink = m_attributes.m_pNext; pLink; pLink = pLink->m_pNext )
+ {
+ nBytes += sizeof( DmAttributeList_t );
+ }
+ return nBytes;
+ }
+
+ DmElementHandle_t m_hElement;
+ unsigned short m_nWeakHandleCount; // CDmeHandle<T> - for auto-hookup once the element comes back, mainly used by UI
+ unsigned short m_nStrongHandleCount; // CDmeCountedElementRef - for preventing elements from being truly deleted, mainly used by undo and file root
+ DmAttributeList_t m_attributes;
+};
+
+
+//-----------------------------------------------------------------------------
+// Base DmElement we inherit from in higher-level classes
+//-----------------------------------------------------------------------------
+class CDmElement
+{
+public:
+ // Can be overridden by derived classes
+ virtual void OnAttributeChanged( CDmAttribute *pAttribute ) {}
+ virtual void PreAttributeChanged( CDmAttribute *pAttribute ) {}
+ virtual void OnAttributeArrayElementAdded( CDmAttribute *pAttribute, int nFirstElem, int nLastElem ) {}
+ virtual void OnAttributeArrayElementRemoved( CDmAttribute *pAttribute, int nFirstElem, int nLastElem ) {}
+ virtual void Resolve() {}
+ virtual bool IsA( UtlSymId_t typeSymbol ) const;
+ virtual int GetInheritanceDepth( UtlSymId_t typeSymbol ) const;
+ virtual void OnElementUnserialized() {}
+ virtual int AllocatedSize() const { return sizeof( CDmElement ); }
+
+ // Returns the element handle
+ DmElementHandle_t GetHandle() const;
+
+ // Attribute iteration, finding
+ // NOTE: Passing a type into GetAttribute will return NULL if the attribute exists but isn't that type
+ bool HasAttribute( const char *pAttributeName, DmAttributeType_t type = AT_UNKNOWN ) const;
+ CDmAttribute *GetAttribute( const char *pAttributeName, DmAttributeType_t type = AT_UNKNOWN );
+ const CDmAttribute *GetAttribute( const char *pAttributeName, DmAttributeType_t type = AT_UNKNOWN ) const;
+ int AttributeCount() const;
+ CDmAttribute* FirstAttribute();
+ const CDmAttribute* FirstAttribute() const;
+
+ // Element name, type, ID
+ // WARNING: SetType() should only be used by format conversion methods (dmxconvert)
+ UtlSymId_t GetType() const;
+ const char * GetTypeString() const;
+ const char * GetName() const;
+ const DmObjectId_t& GetId() const;
+ void SetType( const char *pType );
+ void SetName( const char* pName );
+
+ // Attribute management
+ CDmAttribute * AddAttribute( const char *pAttributeName, DmAttributeType_t type );
+ template< class E > CDmAttribute* AddAttributeElement( const char *pAttributeName );
+ template< class E > CDmAttribute* AddAttributeElementArray( const char *pAttributeName );
+ void RemoveAttribute( const char *pAttributeName );
+ void RemoveAttributeByPtr( CDmAttribute *pAttributeName );
+ void RenameAttribute( const char *pAttributeName, const char *pNewName );
+
+ // get attribute value
+ template< class T > const T& GetValue( const char *pAttributeName ) const;
+ template< class T > const T& GetValue( const char *pAttributeName, const T& defaultValue ) const;
+ const char * GetValueString( const char *pAttributeName ) const;
+ template< class E > E* GetValueElement( const char *pAttributeName ) const;
+
+ // set attribute value
+ CDmAttribute* SetValue( const char *pAttributeName, const void *value, size_t size );
+ template< class T > CDmAttribute* SetValue( const char *pAttributeName, const T& value );
+ template< class E > CDmAttribute* SetValue( const char *pAttributeName, E* value );
+
+ // set attribute value if the attribute doesn't already exist
+ CDmAttribute* InitValue( const char *pAttributeName, const void *value, size_t size );
+ template< class T > CDmAttribute* InitValue( const char *pAttributeName, const T& value );
+ template< class E > CDmAttribute* InitValue( const char *pAttributeName, E* value );
+
+ // Parses an attribute from a string
+ // Doesn't create an attribute if it doesn't exist and always preserves attribute type
+ void SetValueFromString( const char *pAttributeName, const char *value );
+ const char *GetValueAsString( const char *pAttributeName, char *pBuffer, size_t buflen ) const;
+
+ // Helpers for our RTTI
+ template< class E > bool IsA() const;
+ bool IsA( const char *pTypeName ) const;
+ int GetInheritanceDepth( const char *pTypeName ) const;
+ static CUtlSymbol GetStaticTypeSymbol();
+
+ // Indicates whether this element should be copied or not
+ void SetShared( bool bShared );
+ bool IsShared() const;
+
+ // Copies an element and all its attributes
+ CDmElement* Copy( TraversalDepth_t depth = TD_DEEP ) const;
+
+ // Copies attributes from a specified element
+ void CopyAttributesTo( CDmElement *pCopy, TraversalDepth_t depth = TD_DEEP ) const;
+
+ // recursively set fileid's, with option to only change elements in the matched file
+ void SetFileId( DmFileId_t fileid, TraversalDepth_t depth, bool bOnlyIfMatch = false );
+ DmFileId_t GetFileId() const;
+
+ bool IsAccessible() const;
+ void MarkAccessible( bool bAccessible );
+ void MarkAccessible( TraversalDepth_t depth = TD_ALL );
+
+ // returns the first path to the element found traversing all element/element
+ // array attributes - not necessarily the shortest.
+ // cycle-safe (skips any references to elements in the current path)
+ // but may re-traverse elements via different paths
+ bool FindElement( const CDmElement *pElement, CUtlVector< ElementPathItem_t > &elementPath, TraversalDepth_t depth ) const;
+ bool FindReferer( DmElementHandle_t hElement, CUtlVector< ElementPathItem_t > &elementPath, TraversalDepth_t depth ) const;
+ void RemoveAllReferencesToElement( CDmElement *pElement );
+ bool IsStronglyReferenced() { return m_ref.IsStronglyReferenced(); }
+
+ // Estimates the memory usage of the element, its attributes, and child elements
+ int EstimateMemoryUsage( TraversalDepth_t depth = TD_DEEP );
+
+protected:
+ // NOTE: These are protected to ensure that the factory is the only thing that can create these
+ CDmElement( DmElementHandle_t handle, const char *objectType, const DmObjectId_t &id, const char *objectName, DmFileId_t fileid );
+ virtual ~CDmElement();
+
+ // Used by derived classes to do construction and setting up CDmaVars
+ void OnConstruction() { }
+ void OnDestruction() { }
+ virtual void PerformConstruction();
+ virtual void PerformDestruction();
+
+ // Internal methods related to RTII
+ static void SetTypeSymbol( CUtlSymbol sym );
+ static bool IsA_Implementation( CUtlSymbol typeSymbol );
+ static int GetInheritanceDepth_Implementation( CUtlSymbol typeSymbol, int nCurrentDepth );
+
+ // Internal method for creating a copy of this element
+ CDmElement* CopyInternal( TraversalDepth_t depth = TD_DEEP ) const;
+
+ // helper for making attributevarelementarray cleanup easier
+ template< class T > static void DeleteAttributeVarElementArray( T &array );
+
+private:
+ typedef CUtlMap< DmElementHandle_t, DmElementHandle_t, int > CRefMap;
+
+ // Bogus constructor
+ CDmElement();
+
+ // internal recursive copy method - builds refmap of old element's handle -> copy's handle, and uses it to fixup references
+ void CopyAttributesTo( CDmElement *pCopy, CRefMap &refmap, TraversalDepth_t depth ) const;
+ void CopyElementAttribute( const CDmAttribute *pAttr, CDmAttribute *pCopyAttr, CRefMap &refmap, TraversalDepth_t depth ) const;
+ void CopyElementArrayAttribute( const CDmAttribute *pAttr, CDmAttribute *pCopyAttr, CRefMap &refmap, TraversalDepth_t depth ) const;
+ void FixupReferences( CUtlHashFast< DmElementHandle_t > &visited, const CRefMap &refmap, TraversalDepth_t depth );
+
+ void SetFileId( DmFileId_t fileid );
+ void SetFileId_R( CUtlHashFast< DmElementHandle_t > &visited, DmFileId_t fileid, TraversalDepth_t depth, DmFileId_t match, bool bOnlyIfMatch );
+
+ CDmAttribute* CreateAttribute( const char *pAttributeName, DmAttributeType_t type );
+ void RemoveAttribute( CDmAttribute **pAttrRef );
+ CDmAttribute* AddExternalAttribute( const char *pAttributeName, DmAttributeType_t type, void *pMemory );
+ CDmAttribute *FindAttribute( const char *pAttributeName ) const;
+
+ void Purge();
+ void SetId( const DmObjectId_t &id );
+
+ bool IsDirty() const;
+ void MarkDirty( bool dirty = true );
+ void MarkAttributesClean();
+ void MarkBeingUnserialized( bool beingUnserialized = true );
+ bool IsBeingUnserialized() const;
+
+ // Used by the undo system only.
+ void AddAttributeByPtr( CDmAttribute *ptr );
+ void RemoveAttributeByPtrNoDelete( CDmAttribute *ptr );
+
+ // Should only be called from datamodel, who will take care of changing the fileset entry as well
+ void ChangeHandle( DmElementHandle_t handle );
+
+ // returns element reference struct w/ list of referrers and handle count
+ DmElementReference_t* GetReference();
+ void SetReference( const DmElementReference_t &ref );
+
+ // Estimates memory usage
+ int EstimateMemoryUsage( CUtlHash< DmElementHandle_t > &visited, TraversalDepth_t depth, int *pCategories );
+
+protected:
+ CDmaString m_Name;
+
+private:
+ CDmAttribute *m_pAttributes;
+ DmElementReference_t m_ref;
+ UtlSymId_t m_Type;
+ bool m_bDirty : 1;
+ bool m_bBeingUnserialized : 1;
+ bool m_bIsAcessible : 1;
+ unsigned char m_nReserved; // Makes Id be quad aligned
+ DmObjectId_t m_Id;
+ DmFileId_t m_fileId;
+
+ // Stores the type symbol
+ static CUtlSymbol m_classType;
+
+ // Factories can access our constructors
+ template <class T> friend class CDmElementFactory;
+ template <class T> friend class CDmAbstractElementFactory;
+ template< class T > friend class CDmaVar;
+ template< class T > friend class CDmaArray;
+ template< class T > friend class CDmaElementArray;
+ template< class T, class B > friend class CDmaDecorator;
+ template< class T > friend class CDmrElementArray;
+
+ friend class CDmElementFactoryDefault;
+ friend class CDmeElementAccessor;
+ friend class CDmeOperator;
+
+ friend void CopyElements( const CUtlVector< CDmElement* > &from, CUtlVector< CDmElement* > &to, TraversalDepth_t depth );
+};
+
+
+
+inline void DestroyElement( CDmElement *pElement )
+{
+ if ( pElement )
+ {
+ g_pDataModel->DestroyElement( pElement->GetHandle() );
+ }
+}
+
+void DestroyElement( CDmElement *pElement, TraversalDepth_t depth );
+
+
+//-----------------------------------------------------------------------------
+// copy groups of elements together so that references between them are maintained
+//-----------------------------------------------------------------------------
+void CopyElements( const CUtlVector< CDmElement* > &from, CUtlVector< CDmElement* > &to, TraversalDepth_t depth = TD_DEEP );
+
+
+//-----------------------------------------------------------------------------
+// allows elements to chain OnAttributeChanged up to their parents (or at least, referrers)
+//-----------------------------------------------------------------------------
+void InvokeOnAttributeChangedOnReferrers( DmElementHandle_t hElement, CDmAttribute *pChangedAttr );
+
+
+
+
+
+//-----------------------------------------------------------------------------
+// Returns the type, name, id, fileId
+//-----------------------------------------------------------------------------
+inline UtlSymId_t CDmElement::GetType() const
+{
+ return m_Type;
+}
+
+inline const char *CDmElement::GetTypeString() const
+{
+ return g_pDataModel->GetString( m_Type );
+}
+
+inline const char *CDmElement::GetName() const
+{
+ return m_Name.Get();
+}
+
+inline void CDmElement::SetName( const char* pName )
+{
+ m_Name.Set( pName );
+}
+
+inline const DmObjectId_t& CDmElement::GetId() const
+{
+ return m_Id;
+}
+
+inline DmFileId_t CDmElement::GetFileId() const
+{
+ return m_fileId;
+}
+
+
+//-----------------------------------------------------------------------------
+// Controls whether the element should be copied by default
+//-----------------------------------------------------------------------------
+inline void CDmElement::SetShared( bool bShared )
+{
+ if ( bShared )
+ {
+ SetValue< bool >( "shared", true );
+ }
+ else
+ {
+ RemoveAttribute( "shared" );
+ }
+}
+
+inline bool CDmElement::IsShared() const
+{
+ return GetValue< bool >( "shared" ); // if attribute doesn't exist, returns default bool value, which is false
+}
+
+
+//-----------------------------------------------------------------------------
+// Copies attributes from a specified element
+//-----------------------------------------------------------------------------
+inline CDmElement* CDmElement::Copy( TraversalDepth_t depth ) const
+{
+ return CopyInternal( depth );
+}
+
+
+//-----------------------------------------------------------------------------
+// RTTI
+//-----------------------------------------------------------------------------
+inline bool CDmElement::IsA_Implementation( CUtlSymbol typeSymbol )
+{
+ return ( m_classType == typeSymbol ) || ( UTL_INVAL_SYMBOL == typeSymbol );
+}
+
+inline int CDmElement::GetInheritanceDepth_Implementation( CUtlSymbol typeSymbol, int nCurrentDepth )
+{
+ return IsA_Implementation( typeSymbol ) ? nCurrentDepth : -1;
+}
+
+inline CUtlSymbol CDmElement::GetStaticTypeSymbol()
+{
+ return m_classType;
+}
+
+inline bool CDmElement::IsA( const char *pTypeName ) const
+{
+ CUtlSymbol typeSymbol = g_pDataModel->GetSymbol( pTypeName );
+ return IsA( typeSymbol );
+}
+
+template< class E > inline bool CDmElement::IsA() const
+{
+ return IsA( E::GetStaticTypeSymbol() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Helper for finding elements that refer to this element
+//-----------------------------------------------------------------------------
+template< class T >
+T *FindReferringElement( CDmElement *pElement, const char *pAttrName, bool bMustBeInSameFile = true )
+{
+ return FindReferringElement< T >( pElement, g_pDataModel->GetSymbol( pAttrName ), bMustBeInSameFile );
+}
+
+
+void RemoveElementFromRefereringAttributes( CDmElement *pElement, bool bPreserveOrder = true );
+
+
+
+//-----------------------------------------------------------------------------
+//
+// element-specific unique name generation methods
+//
+//-----------------------------------------------------------------------------
+
+// returns startindex if none found, 2 if only "prefix" found, and n+1 if "prefixn" found
+int GenerateUniqueNameIndex( const char *prefix, const CUtlVector< DmElementHandle_t > &array, int startindex = -1 );
+
+bool GenerateUniqueName( char *name, int memsize, const char *prefix, const CUtlVector< DmElementHandle_t > &array );
+
+void MakeElementNameUnique( CDmElement *pElement, const char *prefix, const CUtlVector< DmElementHandle_t > &array, bool forceIndex = false );
+
+
+//-----------------------------------------------------------------------------
+// helper for making attributevarelementarray cleanup easier
+//-----------------------------------------------------------------------------
+template< class T >
+inline void CDmElement::DeleteAttributeVarElementArray( T &array )
+{
+ int nElements = array.Count();
+ for ( int i = 0; i < nElements; ++i )
+ {
+ g_pDataModel->DestroyElement( array.GetHandle( i ) );
+ }
+ array.RemoveAll();
+}
+
+
+//-----------------------------------------------------------------------------
+// Default size computation
+//-----------------------------------------------------------------------------
+template< class T >
+int DmeEstimateMemorySize( T* pElement )
+{
+ return sizeof( T );
+}
+
+
+//-----------------------------------------------------------------------------
+// Helper macro to create an element; this is used for elements that are helper base classes
+//-----------------------------------------------------------------------------
+#define DEFINE_UNINSTANCEABLE_ELEMENT( className, baseClassName ) \
+ protected: \
+ className( DmElementHandle_t handle, const char *pElementTypeName, const DmObjectId_t &id, const char *pElementName, DmFileId_t fileid ) : \
+ baseClassName( handle, pElementTypeName, id, pElementName, fileid ) \
+ { \
+ } \
+ virtual ~className() \
+ { \
+ } \
+ void OnConstruction(); \
+ void OnDestruction(); \
+ virtual void PerformConstruction() \
+ { \
+ BaseClass::PerformConstruction(); \
+ OnConstruction(); \
+ } \
+ virtual void PerformDestruction() \
+ { \
+ OnDestruction(); \
+ BaseClass::PerformDestruction(); \
+ } \
+ virtual int AllocatedSize() const { return DmeEstimateMemorySize( this ); } \
+ \
+ private: \
+ typedef baseClassName BaseClass; \
+
+
+//-----------------------------------------------------------------------------
+// Helper macro to create the class factory
+//-----------------------------------------------------------------------------
+#define DEFINE_ELEMENT( className, baseClassName ) \
+ public: \
+ virtual bool IsA( UtlSymId_t typeSymbol ) const \
+ { \
+ return IsA_Implementation( typeSymbol );\
+ } \
+ \
+ bool IsA( const char *pTypeName ) const \
+ { \
+ CUtlSymbol typeSymbol = g_pDataModel->GetSymbol( pTypeName ); \
+ return IsA( typeSymbol ); \
+ } \
+ \
+ template< class T > bool IsA() const \
+ { \
+ return IsA( T::GetStaticTypeSymbol() ); \
+ } \
+ \
+ virtual int GetInheritanceDepth( UtlSymId_t typeSymbol ) const \
+ { \
+ return GetInheritanceDepth_Implementation( typeSymbol, 0 ); \
+ } \
+ \
+ static CUtlSymbol GetStaticTypeSymbol( ) \
+ { \
+ return m_classType; \
+ } \
+ \
+ className* Copy( TraversalDepth_t depth = TD_DEEP ) const \
+ { \
+ return static_cast< className* >( CopyInternal( depth ) ); \
+ } \
+ protected: \
+ className( DmElementHandle_t handle, const char *pElementTypeName, const DmObjectId_t &id, const char *pElementName, DmFileId_t fileid ) : \
+ baseClassName( handle, pElementTypeName, id, pElementName, fileid ) \
+ { \
+ } \
+ virtual ~className() \
+ { \
+ } \
+ void OnConstruction(); \
+ void OnDestruction(); \
+ virtual void PerformConstruction() \
+ { \
+ BaseClass::PerformConstruction(); \
+ OnConstruction(); \
+ } \
+ virtual void PerformDestruction() \
+ { \
+ OnDestruction(); \
+ BaseClass::PerformDestruction(); \
+ } \
+ static void SetTypeSymbol( CUtlSymbol typeSymbol ) \
+ { \
+ m_classType = typeSymbol; \
+ } \
+ \
+ static bool IsA_Implementation( CUtlSymbol typeSymbol ) \
+ { \
+ if ( typeSymbol == m_classType ) \
+ return true; \
+ return BaseClass::IsA_Implementation( typeSymbol ); \
+ } \
+ \
+ static int GetInheritanceDepth_Implementation( CUtlSymbol typeSymbol, int nCurrentDepth ) \
+ { \
+ if ( typeSymbol == m_classType ) \
+ return nCurrentDepth; \
+ return BaseClass::GetInheritanceDepth_Implementation( typeSymbol, nCurrentDepth+1 );\
+ } \
+ virtual int AllocatedSize() const { return DmeEstimateMemorySize( this ); } \
+ \
+ private: \
+ typedef baseClassName BaseClass; \
+ template <class T> friend class CDmElementFactory; \
+ template <class T> friend class CDmAbstractElementFactory; \
+ static CUtlSymbol m_classType
+
+#define IMPLEMENT_ELEMENT( className ) \
+ CUtlSymbol className::m_classType = UTL_INVAL_SYMBOL;
+
+
+#endif // DMELEMENT_H
diff --git a/sp/src/public/datamodel/dmelementfactoryhelper.h b/sp/src/public/datamodel/dmelementfactoryhelper.h
new file mode 100644
index 00000000..f0729063
--- /dev/null
+++ b/sp/src/public/datamodel/dmelementfactoryhelper.h
@@ -0,0 +1,190 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef DMELEMENTFACTORYHELPER_H
+#define DMELEMENTFACTORYHELPER_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "datamodel/idatamodel.h"
+#include "datamodel/dmelement.h"
+#include "datamodel/dmattribute.h"
+#include "datamodel/dmattributevar.h"
+#include "tier1/utlvector.h"
+#include "tier1/utlsymbol.h"
+
+
+//-----------------------------------------------------------------------------
+// Internal interface for IDmElementFactory
+//-----------------------------------------------------------------------------
+class IDmElementFactoryInternal : public IDmElementFactory
+{
+public:
+ virtual void SetElementTypeSymbol( CUtlSymbol sym ) = 0;
+ virtual bool IsAbstract() const = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// Class used to register factories into a global list
+//-----------------------------------------------------------------------------
+class CDmElementFactoryHelper
+{
+public:
+ // Static list of helpers
+ static CDmElementFactoryHelper *s_pHelpers[2];
+
+ // Create all the hud elements
+ static void InstallFactories( );
+
+public:
+ // Construction
+ CDmElementFactoryHelper( const char *pClassName, IDmElementFactoryInternal *pFactory, bool bIsStandardFactory );
+
+ // Accessors
+ CDmElementFactoryHelper *GetNext( void );
+
+ const char *GetClassname();
+ IDmElementFactoryInternal *GetFactory();
+
+private:
+ // Next factory in list
+ CDmElementFactoryHelper *m_pNext;
+ // Creation function to use for this technology
+ IDmElementFactoryInternal *m_pFactory;
+ const char *m_pszClassname;
+};
+
+
+//-----------------------------------------------------------------------------
+// Inline methods
+//-----------------------------------------------------------------------------
+inline const char *CDmElementFactoryHelper::GetClassname()
+{
+ return m_pszClassname;
+}
+
+inline IDmElementFactoryInternal *CDmElementFactoryHelper::GetFactory()
+{
+ return m_pFactory;
+}
+
+
+//-----------------------------------------------------------------------------
+// Helper Template factory for simple creation of factories
+//-----------------------------------------------------------------------------
+template <class T >
+class CDmElementFactory : public IDmElementFactoryInternal
+{
+public:
+ CDmElementFactory( const char *pLookupName ) : m_pLookupName( pLookupName ) {}
+
+ // Creation, destruction
+ virtual CDmElement* Create( DmElementHandle_t handle, const char *pElementType, const char *pElementName, DmFileId_t fileid, const DmObjectId_t &id )
+ {
+ return new T( handle, m_pLookupName, id, pElementName, fileid );
+ }
+
+ virtual void Destroy( DmElementHandle_t hElement )
+ {
+ CDmElement *pElement = g_pDataModel->GetElement( hElement );
+ if ( pElement )
+ {
+ T *pActualElement = static_cast< T* >( pElement );
+ delete pActualElement;
+ }
+ }
+
+ // Sets the type symbol, used for "isa" implementation
+ virtual void SetElementTypeSymbol( CUtlSymbol sym )
+ {
+ T::SetTypeSymbol( sym );
+ }
+
+ virtual bool IsAbstract() const { return false; }
+
+private:
+ const char *m_pLookupName;
+};
+
+
+template < class T >
+class CDmAbstractElementFactory : public IDmElementFactoryInternal
+{
+public:
+ CDmAbstractElementFactory() {}
+
+ // Creation, destruction
+ virtual CDmElement* Create( DmElementHandle_t handle, const char *pElementType, const char *pElementName, DmFileId_t fileid, const DmObjectId_t &id )
+ {
+ return NULL;
+ }
+
+ virtual void Destroy( DmElementHandle_t hElement )
+ {
+ }
+
+ // Sets the type symbol, used for "isa" implementation
+ virtual void SetElementTypeSymbol( CUtlSymbol sym )
+ {
+ T::SetTypeSymbol( sym );
+ }
+
+ virtual bool IsAbstract() const { return true; }
+
+private:
+};
+
+
+//-----------------------------------------------------------------------------
+// Helper macro to create the class factory
+//-----------------------------------------------------------------------------
+#if defined( MOVIEOBJECTS_LIB ) || defined ( DATAMODEL_LIB ) || defined ( DMECONTROLS_LIB )
+
+#define IMPLEMENT_ELEMENT_FACTORY( lookupName, className ) \
+ IMPLEMENT_ELEMENT( className ) \
+ CDmElementFactory< className > g_##className##_Factory( #lookupName ); \
+ CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, true ); \
+ className *g_##className##LinkerHack = NULL;
+
+#define IMPLEMENT_ABSTRACT_ELEMENT( lookupName, className ) \
+ IMPLEMENT_ELEMENT( className ) \
+ CDmAbstractElementFactory< className > g_##className##_Factory; \
+ CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, true ); \
+ className *g_##className##LinkerHack = NULL;
+
+#else
+
+#define IMPLEMENT_ELEMENT_FACTORY( lookupName, className ) \
+ IMPLEMENT_ELEMENT( className ) \
+ CDmElementFactory< className > g_##className##_Factory( #lookupName ); \
+ CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, false ); \
+ className *g_##className##LinkerHack = NULL;
+
+#define IMPLEMENT_ABSTRACT_ELEMENT( lookupName, className ) \
+ IMPLEMENT_ELEMENT( className ) \
+ CDmAbstractElementFactory< className > g_##className##_Factory; \
+ CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, false ); \
+ className *g_##className##LinkerHack = NULL;
+
+#endif
+
+
+// Used by classes defined in movieobjects or scenedatabase that must be explicitly installed
+#define IMPLEMENT_ELEMENT_FACTORY_INSTALL_EXPLICITLY( lookupName, className ) \
+ IMPLEMENT_ELEMENT( className ) \
+ CDmElementFactory< className > g_##className##_Factory( #lookupName ); \
+ CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, false ); \
+ className *g_##className##LinkerHack = NULL;
+
+//-----------------------------------------------------------------------------
+// Installs dm element factories
+//-----------------------------------------------------------------------------
+void InstallDmElementFactories( );
+
+
+#endif // DMELEMENTFACTORYHELPER_H
diff --git a/sp/src/public/datamodel/dmelementhandle.h b/sp/src/public/datamodel/dmelementhandle.h
new file mode 100644
index 00000000..6a96cc1d
--- /dev/null
+++ b/sp/src/public/datamodel/dmelementhandle.h
@@ -0,0 +1,47 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef DMELEMENTHANDLE_H
+#define DMELEMENTHANDLE_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+//-----------------------------------------------------------------------------
+// handle to an CDmElement
+//-----------------------------------------------------------------------------
+#define PERFORM_HANDLE_TYPECHECKING 0
+#if PERFORM_HANDLE_TYPECHECKING
+
+// this is here to make sure we're being type-safe about element handles
+// otherwise, the compiler lets us cast to bool incorrectly
+// the other solution would be to redefine DmElementHandle_t s.t. DMELEMENT_HANDLE_INVALID==0
+struct DmElementHandle_t
+{
+ DmElementHandle_t() : handle( 0xffffffff ) {}
+ explicit DmElementHandle_t( int h ) : handle( h ) {}
+ inline bool operator==( const DmElementHandle_t &h ) const { return handle == h.handle; }
+ inline bool operator!=( const DmElementHandle_t &h ) const { return handle != h.handle; }
+ inline bool operator<( const DmElementHandle_t &h ) const { return handle < h.handle; }
+// inline operator int() const { return handle; } // if we're okay with implicit int casts, uncomment this method
+ int handle;
+};
+const DmElementHandle_t DMELEMENT_HANDLE_INVALID;
+
+#else // PERFORM_HANDLE_TYPECHECKING
+
+enum DmElementHandle_t
+{
+ DMELEMENT_HANDLE_INVALID = 0xffffffff
+};
+
+#endif // PERFORM_HANDLE_TYPECHECKING
+
+
+
+#endif // DMELEMENTHANDLE_H
diff --git a/sp/src/public/datamodel/dmvar.h b/sp/src/public/datamodel/dmvar.h
new file mode 100644
index 00000000..c19c2896
--- /dev/null
+++ b/sp/src/public/datamodel/dmvar.h
@@ -0,0 +1,93 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef DMVAR_H
+#define DMVAR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+class CDmAttribute;
+
+//-----------------------------------------------------------------------------
+// Helper template for external attributes
+//-----------------------------------------------------------------------------
+template< typename T >
+class CDmaVar
+{
+ typedef typename CDmAttributeInfo< T >::StorageType_t D;
+
+public:
+ CDmaVar( );
+
+ // Setup to be used in OnConstruction methods of DmElements
+ void Init( CDmElement *pOwner, const char *pAttributeName, int flags = 0 );
+ void InitAndSet( CDmElement *pOwner, const char *pAttributeName, const T &value, int flags = 0 );
+
+ // Set/get
+ const T& Set( const T &val );
+ const T& Get() const;
+
+ // Cast operators
+ operator const T&() const;
+ const T* operator->() const;
+
+ // Assignment operator
+ const CDmaVar<T>& operator=( const CDmaVar<T>& src );
+
+ // Math utility operations
+ const T& operator=( const T &val );
+ const T& operator+=( const T &val );
+ const T& operator-=( const T &val );
+ const T& operator/=( const T &val );
+ const T& operator*=( const T &val );
+ const T& operator^=( const T &val );
+ const T& operator|=( const T &val );
+ const T& operator&=( const T &val );
+ T operator++();
+ T operator--();
+ T operator++( int ); // postfix version..
+ T operator--( int ); // postfix version..
+
+ // Returns the attribute associated with the var
+ CDmAttribute *GetAttribute();
+ const CDmAttribute *GetAttribute() const;
+
+ // Is the attribute dirty?
+ bool IsDirty() const;
+
+protected:
+ const T& Value() const;
+ T& Value();
+ const D& Storage() const;
+ D& Storage();
+
+private:
+ D m_Storage;
+
+protected:
+ CDmAttribute *m_pAttribute;
+};
+
+//-----------------------------------------------------------------------------
+// Specialization for string
+//-----------------------------------------------------------------------------
+class CDmaString : public CDmaVar< CUtlString >
+{
+public:
+ const char *Get( ) const;
+ operator const char*() const;
+
+ void Set( const char *pValue );
+ CDmaString &operator=( const char *src );
+ const CDmaString& operator=( const CDmaString& src );
+
+ // Returns strlen
+ int Length() const;
+};
+
+#endif // DMVAR_H
diff --git a/sp/src/public/datamodel/idatamodel.h b/sp/src/public/datamodel/idatamodel.h
new file mode 100644
index 00000000..d120c226
--- /dev/null
+++ b/sp/src/public/datamodel/idatamodel.h
@@ -0,0 +1,938 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#ifndef IDATAMODEL_H
+#define IDATAMODEL_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier1/interface.h"
+#include "tier1/utlvector.h"
+#include "tier1/utlsymbol.h"
+#include "appframework/IAppSystem.h"
+#include "datamodel/dmattributetypes.h"
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations:
+//-----------------------------------------------------------------------------
+class CDmAttribute;
+class CDmElement;
+class IDmeOperator;
+class IElementForKeyValueCallback;
+
+struct DmValueBase_t;
+class CUtlBuffer;
+class KeyValues;
+class CUtlSymbolTable;
+class CUtlCharConversion;
+
+
+//-----------------------------------------------------------------------------
+// data file format info
+//-----------------------------------------------------------------------------
+#define DMX_LEGACY_VERSION_STARTING_TOKEN "<!-- DMXVersion"
+#define DMX_LEGACY_VERSION_ENDING_TOKEN "-->"
+
+#define DMX_VERSION_STARTING_TOKEN "<!-- dmx"
+#define DMX_VERSION_ENDING_TOKEN "-->"
+
+#define GENERIC_DMX_FORMAT "dmx"
+
+
+enum
+{
+ DMX_MAX_FORMAT_NAME_MAX_LENGTH = 64,
+ DMX_MAX_HEADER_LENGTH = 40 + 2 * DMX_MAX_FORMAT_NAME_MAX_LENGTH,
+};
+
+struct DmxHeader_t
+{
+ char encodingName[ DMX_MAX_FORMAT_NAME_MAX_LENGTH ];
+ int nEncodingVersion;
+ char formatName[ DMX_MAX_FORMAT_NAME_MAX_LENGTH ];
+ int nFormatVersion;
+
+ DmxHeader_t() : nEncodingVersion( -1 ), nFormatVersion( -1 )
+ {
+ encodingName[ 0 ] = formatName[ 0 ] = '\0';
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+// element framework phases
+//-----------------------------------------------------------------------------
+enum DmPhase_t
+{
+ PH_EDIT,
+ PH_EDIT_APPLY,
+ PH_EDIT_RESOLVE,
+ PH_DEPENDENCY,
+ PH_OPERATE,
+ PH_OPERATE_RESOLVE,
+ PH_OUTPUT,
+};
+
+
+//-----------------------------------------------------------------------------
+// file id - also used to refer to elements that don't have file associations
+//-----------------------------------------------------------------------------
+enum DmFileId_t
+{
+ DMFILEID_INVALID = 0xffffffff
+};
+
+//-----------------------------------------------------------------------------
+// Handle to an CDmAttribute
+//-----------------------------------------------------------------------------
+enum DmAttributeHandle_t
+{
+ DMATTRIBUTE_HANDLE_INVALID = 0xffffffff
+};
+
+//-----------------------------------------------------------------------------
+// Handle to an DmAttributeList_t
+//-----------------------------------------------------------------------------
+enum DmAttributeReferenceIterator_t
+{
+ DMATTRIBUTE_REFERENCE_ITERATOR_INVALID = 0
+};
+
+//-----------------------------------------------------------------------------
+// element framework interface
+//-----------------------------------------------------------------------------
+abstract_class IDmElementFramework : public IAppSystem
+{
+public:
+ // Methods of IAppSystem
+ virtual bool Connect( CreateInterfaceFn factory ) = 0;
+ virtual void Disconnect() = 0;
+ virtual void *QueryInterface( const char *pInterfaceName ) = 0;
+ virtual InitReturnVal_t Init() = 0;
+ virtual void Shutdown() = 0;
+
+ virtual DmPhase_t GetPhase() = 0;
+
+ virtual void SetOperators( const CUtlVector< IDmeOperator* > &operators ) = 0;
+
+ virtual void BeginEdit() = 0; // ends in edit phase, forces apply/resolve if from edit phase
+ virtual void Operate( bool bResolve ) = 0; // ends in output phase
+ virtual void Resolve() = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// Used only by aplpications to hook in the element framework
+//-----------------------------------------------------------------------------
+#define VDMELEMENTFRAMEWORK_VERSION "VDmElementFrameworkVersion001"
+
+
+//-----------------------------------------------------------------------------
+// Main interface
+//-----------------------------------------------------------------------------
+extern IDmElementFramework *g_pDmElementFramework;
+
+
+//-----------------------------------------------------------------------------
+// datamodel operator interface - for all elements that need to be sorted in the operator dependency graph
+//-----------------------------------------------------------------------------
+abstract_class IDmeOperator
+{
+public:
+ virtual bool IsDirty() = 0; // ie needs to operate
+ virtual void Operate() = 0;
+
+ virtual void GetInputAttributes ( CUtlVector< CDmAttribute * > &attrs ) = 0;
+ virtual void GetOutputAttributes( CUtlVector< CDmAttribute * > &attrs ) = 0;
+};
+
+//-----------------------------------------------------------------------------
+// Class factory methods:
+//-----------------------------------------------------------------------------
+class IDmElementFactory
+{
+public:
+ // Creation, destruction
+ virtual CDmElement* Create( DmElementHandle_t handle, const char *pElementType, const char *pElementName, DmFileId_t fileid, const DmObjectId_t &id ) = 0;
+ virtual void Destroy( DmElementHandle_t hElement ) = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// Various serialization methods can be installed into the data model factory
+//-----------------------------------------------------------------------------
+enum DmConflictResolution_t
+{
+ CR_DELETE_NEW,
+ CR_DELETE_OLD,
+ CR_COPY_NEW,
+ CR_FORCE_COPY,
+};
+
+// convert files to elements and back
+// current file encodings supported: binary, xml, xml_flat, keyvalues2, keyvalues2_flat, keyvalues (vmf/vmt/actbusy), text? (qc/obj)
+class IDmSerializer
+{
+public:
+ virtual const char *GetName() const = 0;
+ virtual const char *GetDescription() const = 0;
+ virtual bool IsBinaryFormat() const = 0;
+ virtual bool StoresVersionInFile() const = 0;
+ virtual int GetCurrentVersion() const = 0;
+
+ // Write into the UtlBuffer, return true if successful
+ // if we decide to implement non-identity conversions between formats on write, then the source and dest format will need to be passed in here
+ virtual bool Serialize( CUtlBuffer &buf, CDmElement *pRoot ) = 0;
+
+ // Read from the UtlBuffer, return true if successful, and return the read-in root in ppRoot.
+ virtual bool Unserialize( CUtlBuffer &buf, const char *pEncodingName, int nEncodingVersion,
+ const char *pSourceFormatName, int nSourceFormatVersion,
+ DmFileId_t fileid, DmConflictResolution_t idConflictResolution, CDmElement **ppRoot ) = 0;
+};
+
+// convert legacy elements to non-legacy elements
+// legacy formats include: sfm_vN, binary_vN, keyvalues2_v1, keyvalues2_flat_v1, xml, xml_flat
+// where N is a version number (1..9 for sfm, 1..2 for binary)
+class IDmLegacyUpdater
+{
+public:
+ virtual const char *GetName() const = 0;
+ virtual bool IsLatestVersion() const = 0;
+
+ // Updates ppRoot to first non-legacy generic dmx format, returns false if the conversion fails
+ virtual bool Update( CDmElement **ppRoot ) = 0;
+};
+
+// converts old elements to new elements
+// current formats include: sfm session, animset presets, particle definitions, exported maya character, etc.
+class IDmFormatUpdater
+{
+public:
+ virtual const char *GetName() const = 0;
+ virtual const char *GetDescription() const = 0;
+ virtual const char *GetExtension() const = 0;
+ virtual int GetCurrentVersion() const = 0;
+ virtual const char *GetDefaultEncoding() const = 0;
+
+ // Converts pSourceRoot from nSourceVersion to the current version, returns false if the conversion fails
+ virtual bool Update( CDmElement **pRoot, int nSourceVersion ) = 0;
+};
+
+//-----------------------------------------------------------------------------
+// Interface for callbacks to supply element types for specific keys inside keyvalues files
+//-----------------------------------------------------------------------------
+class IElementForKeyValueCallback
+{
+public:
+ virtual const char *GetElementForKeyValue( const char *pszKeyName, int iNestingLevel ) = 0;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Optional helper passed in with clipboard data which is called when it's time to clean up the clipboard data in case the application
+// had some dynamically allocated data attached to a KV SetPtr object...
+//-----------------------------------------------------------------------------
+abstract_class IClipboardCleanup
+{
+public:
+ virtual void ReleaseClipboardData( CUtlVector< KeyValues * >& list ) = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Can be installed to be called back when data changes
+//-----------------------------------------------------------------------------
+enum DmNotifySource_t
+{
+ // Sources
+ NOTIFY_SOURCE_APPLICATION = 0,
+ NOTIFY_SOURCE_UNDO,
+ NOTIFY_SOURCE_FIRST_DME_CONTROL_SOURCE = 4, // Sources from dme_controls starts here
+ NOTIFY_SOURCE_FIRST_APPLICATION_SOURCE = 8, // Sources from applications starts here
+};
+
+enum DmNotifyFlags_t
+{
+ // Does this dirty the document?
+ NOTIFY_SOURCE_BITS = 8,
+ NOTIFY_SETDIRTYFLAG = (1<<NOTIFY_SOURCE_BITS),
+
+ // Type of change (note NOTIFY_CHANGE_TOPOLOGICAL/NOTIFY_CHANGE_ATTRIBUTE_VALUE/NOTIFY_CHANGE_ATTRIBUTE_ARRAY_SIZE
+ // are set by the Datamodel itself)
+ NOTIFY_CHANGE_TOPOLOGICAL = (1<<(NOTIFY_SOURCE_BITS+4)), // Element created, destroyed, element attribute or element array attribute value changed
+ NOTIFY_CHANGE_ATTRIBUTE_VALUE = (1<<(NOTIFY_SOURCE_BITS+5)), // Non-element attribute value changed
+ NOTIFY_CHANGE_ATTRIBUTE_ARRAY_SIZE = (1<<(NOTIFY_SOURCE_BITS+6)), // Non-element array attribute added or removed
+ NOTIFY_CHANGE_OTHER = (1<<(NOTIFY_SOURCE_BITS+7)), // Non attribute related change (a change in UI, for example)
+
+ NOTIFY_CHANGE_MASK = ( NOTIFY_CHANGE_TOPOLOGICAL | NOTIFY_CHANGE_ATTRIBUTE_VALUE | NOTIFY_CHANGE_ATTRIBUTE_ARRAY_SIZE | NOTIFY_CHANGE_OTHER ),
+
+};
+
+abstract_class IDmNotify
+{
+public:
+ // See DmNotifySource_t and DmNotifyFlags_t
+ virtual void NotifyDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags ) = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Helper for debugging undo system
+//-----------------------------------------------------------------------------
+struct UndoInfo_t
+{
+ bool terminator;
+ const char *desc;
+ const char *undo;
+ const char *redo;
+ int numoperations;
+};
+
+
+//-----------------------------------------------------------------------------
+// Interface for undo
+//-----------------------------------------------------------------------------
+abstract_class IUndoElement
+{
+public:
+ virtual void Undo() = 0;
+ virtual void Redo() = 0;
+
+ virtual const char *UndoDesc() const = 0;
+ virtual const char *RedoDesc() const = 0;
+ virtual const char *GetDesc() const = 0;
+ virtual void Release() = 0;
+
+protected:
+ virtual bool IsEndOfStream() const = 0;
+ virtual void SetEndOfStream( bool end ) = 0;
+ virtual ~IUndoElement() { }
+
+ friend class CUndoManager;
+};
+
+//-----------------------------------------------------------------------------
+// traversal depth for copy, search, and other element/attribute traversals
+//-----------------------------------------------------------------------------
+enum TraversalDepth_t
+{
+ TD_ALL, // traverse all attributes
+ TD_DEEP, // traverse attributes with FATTRIB_NEVERCOPY clear
+ TD_SHALLOW, // traverse attributes with FATTRIB_MUSTCOPY set
+ TD_NONE, // don't traverse any attributes
+};
+
+
+//-----------------------------------------------------------------------------
+// Main interface for creation of all IDmeElements:
+//-----------------------------------------------------------------------------
+class IDataModel : public IAppSystem
+{
+public:
+ // Installs factories used to instance elements
+ virtual void AddElementFactory( const char *pElementTypeName, IDmElementFactory *pFactory ) = 0;
+
+ // This factory will be used to instance all elements whose type name isn't found.
+ virtual void SetDefaultElementFactory( IDmElementFactory *pFactory ) = 0;
+
+ virtual int GetFirstFactory() const = 0;
+ virtual int GetNextFactory( int index ) const = 0;
+ virtual bool IsValidFactory( int index ) const = 0;
+ virtual const char *GetFactoryName( int index ) const = 0;
+
+ // create/destroy element methods - proxies to installed element factories
+ virtual DmElementHandle_t CreateElement( UtlSymId_t typeSymbol, const char *pElementName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL ) = 0;
+ virtual DmElementHandle_t CreateElement( const char *pTypeName, const char *pElementName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL ) = 0;
+ virtual void DestroyElement( DmElementHandle_t hElement ) = 0;
+
+ // element handle related methods
+ virtual CDmElement* GetElement ( DmElementHandle_t hElement ) const = 0;
+ virtual UtlSymId_t GetElementType ( DmElementHandle_t hElement ) const = 0;
+ virtual const char* GetElementName ( DmElementHandle_t hElement ) const = 0;
+ virtual const DmObjectId_t& GetElementId ( DmElementHandle_t hElement ) const = 0;
+
+ virtual const char* GetAttributeNameForType( DmAttributeType_t attType ) const = 0;
+ virtual DmAttributeType_t GetAttributeTypeForName( const char *name ) const = 0;
+
+ // Adds various serializers and updaters
+ virtual void AddSerializer( IDmSerializer *pSerializer ) = 0;
+ virtual void AddLegacyUpdater( IDmLegacyUpdater *pUpdater ) = 0;
+ virtual void AddFormatUpdater( IDmFormatUpdater *pUpdater ) = 0;
+
+ // file format methods
+ virtual const char* GetFormatExtension( const char *pFormatName ) = 0;
+ virtual const char* GetFormatDescription( const char *pFormatName ) = 0;
+ virtual int GetFormatCount() const = 0;
+ virtual const char * GetFormatName( int i ) const = 0;
+ virtual const char * GetDefaultEncoding( const char *pFormatName ) = 0;
+
+ // file encoding methods
+ virtual int GetEncodingCount() const = 0;
+ virtual const char * GetEncodingName( int i ) const = 0;
+ virtual bool IsEncodingBinary( const char *pEncodingName ) const = 0;
+ virtual bool DoesEncodingStoreVersionInFile( const char *pEncodingName ) const = 0;
+
+ // For serialization, set the delimiter rules
+ // These methods are meant to be used by importer/exporters
+ virtual void SetSerializationDelimiter( CUtlCharConversion *pConv ) = 0;
+ virtual void SetSerializationArrayDelimiter( const char *pDelimiter ) = 0;
+
+ // used to skip auto-creation of child elements during unserialization
+ virtual bool IsUnserializing() = 0;
+
+ // Serialization of a element tree into a utlbuffer
+ virtual bool Serialize( CUtlBuffer &outBuf, const char *pEncodingName, const char *pFormatName, DmElementHandle_t hRoot ) = 0;
+
+ // Unserializes, returns the root of the unserialized tree in hRoot
+ // The file name passed in is simply for error messages and fileid creation
+ virtual bool Unserialize( CUtlBuffer &inBuf, const char *pEncodingName, const char *pSourceFormatName, const char *pFormatHint,
+ const char *pFileName, DmConflictResolution_t idConflictResolution, DmElementHandle_t &hRoot ) = 0;
+
+ // converts from elements from old file formats to elements for the current file format
+ virtual bool UpdateUnserializedElements( const char *pSourceFormatName, int nSourceFormatVersion,
+ DmFileId_t fileid, DmConflictResolution_t idConflictResolution, CDmElement **ppRoot ) = 0;
+
+ // force creation of untyped elements, ignoring type
+ virtual void OnlyCreateUntypedElements( bool bEnable ) = 0;
+
+ // Finds a serializer by name
+ virtual IDmSerializer* FindSerializer( const char *pEncodingName ) const = 0;
+ virtual IDmLegacyUpdater* FindLegacyUpdater( const char *pLegacyFormatName ) const = 0;
+ virtual IDmFormatUpdater* FindFormatUpdater( const char *pFormatName ) const = 0;
+
+ // saves element tree to a file
+ virtual bool SaveToFile( const char *pFileName, const char *pPathID, const char *pEncodingName, const char *pFormatName, CDmElement *pRoot ) = 0;
+
+ // restores file into an element tree
+ // NOTE: Format name is only used here for those formats which don't store
+ // the format name in the file. Use NULL for those formats which store the
+ // format name in the file.
+ virtual DmFileId_t RestoreFromFile( const char *pFileName, const char *pPathID, const char *pFormatHint, CDmElement **ppRoot, DmConflictResolution_t idConflictResolution = CR_DELETE_NEW, DmxHeader_t *pHeaderOut = NULL ) = 0;
+
+ // Sets the name of the DME element to create in keyvalues serialization
+ virtual void SetKeyValuesElementCallback( IElementForKeyValueCallback *pCallbackInterface ) = 0;
+ virtual const char *GetKeyValuesElementName( const char *pszKeyName, int iNestingLevel ) = 0;
+
+ // Global symbol table for the datamodel system
+ virtual UtlSymId_t GetSymbol( const char *pString ) = 0;
+ virtual const char * GetString( UtlSymId_t sym ) const = 0;
+
+ // Returns the total number of elements allocated at the moment
+ virtual int GetMaxNumberOfElements() = 0;
+ virtual int GetElementsAllocatedSoFar() = 0;
+ virtual int GetAllocatedAttributeCount() = 0;
+ virtual int GetAllocatedElementCount() = 0;
+ virtual DmElementHandle_t FirstAllocatedElement() = 0;
+ virtual DmElementHandle_t NextAllocatedElement( DmElementHandle_t it ) = 0;
+
+ // estimate memory usage
+ virtual int EstimateMemoryUsage( DmElementHandle_t hElement, TraversalDepth_t depth ) = 0;
+
+ // Undo/Redo support
+ virtual void SetUndoEnabled( bool enable ) = 0;
+ virtual bool IsUndoEnabled() const = 0;
+ virtual bool UndoEnabledForElement( const CDmElement *pElement ) const = 0;
+ virtual bool IsDirty() const = 0;
+ virtual bool CanUndo() const = 0;
+ virtual bool CanRedo() const = 0;
+ // If chaining ID is != 0 and the next StartUndo uses the same ID, then the operations will be chained together into a single undo operation
+ virtual void StartUndo( char const *undodesc, char const *redodesc, int nChainingID = 0 ) = 0;
+ virtual void FinishUndo() = 0;
+ virtual void AbortUndoableOperation() = 0; // called instead of FinishUndo, essentially performs and Undo() and WipeRedo() if any undo items have been added to the stack
+ virtual void ClearRedo() = 0;
+ virtual const char *GetUndoDesc() = 0;
+ virtual const char *GetRedoDesc() = 0;
+ // From the UI, perform the Undo operation
+ virtual void Undo() = 0;
+ virtual void Redo() = 0;
+ virtual void TraceUndo( bool state ) = 0; // if true, undo records spew as they are added
+
+ // Wipes out all Undo data
+ virtual void ClearUndo() = 0;
+
+ virtual void GetUndoInfo( CUtlVector< UndoInfo_t >& list ) = 0;
+
+ virtual void AddUndoElement( IUndoElement *pElement ) = 0;
+ virtual UtlSymId_t GetUndoDescInternal( const char *context ) = 0;
+ virtual UtlSymId_t GetRedoDescInternal( const char *context ) = 0;
+
+ virtual void EmptyClipboard() = 0;
+ virtual void SetClipboardData( CUtlVector< KeyValues * >& data, IClipboardCleanup *pfnOptionalCleanuFunction = 0 ) = 0;
+ virtual void AddToClipboardData( KeyValues *add ) = 0;
+ virtual void GetClipboardData( CUtlVector< KeyValues * >& data ) = 0;
+ virtual bool HasClipboardData() const = 0;
+
+ // Handles to attributes
+ virtual CDmAttribute * GetAttribute( DmAttributeHandle_t h ) = 0;
+ virtual bool IsAttributeHandleValid( DmAttributeHandle_t h ) const = 0;
+
+ // file id reference methods
+ virtual int NumFileIds() = 0;
+ virtual DmFileId_t GetFileId( int i ) = 0;
+ virtual DmFileId_t FindOrCreateFileId( const char *pFilename ) = 0;
+ virtual void RemoveFileId( DmFileId_t fileid ) = 0;
+ virtual DmFileId_t GetFileId( const char *pFilename ) = 0;
+ virtual const char * GetFileName( DmFileId_t fileid ) = 0;
+ virtual void SetFileName( DmFileId_t fileid, const char *pFileName ) = 0;
+ virtual const char * GetFileFormat( DmFileId_t fileid ) = 0;
+ virtual void SetFileFormat( DmFileId_t fileid, const char *pFormat ) = 0;
+ virtual DmElementHandle_t GetFileRoot( DmFileId_t fileid ) = 0;
+ virtual void SetFileRoot( DmFileId_t fileid, DmElementHandle_t hRoot ) = 0;
+ virtual bool IsFileLoaded( DmFileId_t fileid ) = 0;
+ virtual void MarkFileLoaded( DmFileId_t fileid ) = 0;
+ virtual void UnloadFile( DmFileId_t fileid ) = 0;
+ virtual int NumElementsInFile( DmFileId_t fileid ) = 0;
+
+ virtual void DontAutoDelete( DmElementHandle_t hElement ) = 0;
+
+ // handle validity methods - these shouldn't really be here, but the undo system needs them...
+ virtual void MarkHandleInvalid( DmElementHandle_t hElement ) = 0;
+ virtual void MarkHandleValid( DmElementHandle_t hElement ) = 0;
+
+ virtual DmElementHandle_t FindElement( const DmObjectId_t &id ) = 0;
+
+ virtual DmAttributeReferenceIterator_t FirstAttributeReferencingElement( DmElementHandle_t hElement ) = 0;
+ virtual DmAttributeReferenceIterator_t NextAttributeReferencingElement( DmAttributeReferenceIterator_t hAttrIter ) = 0;
+ virtual CDmAttribute * GetAttribute( DmAttributeReferenceIterator_t hAttrIter ) = 0;
+
+ // Install, remove notify callbacks associated w/ undo contexts
+ virtual bool InstallNotificationCallback( IDmNotify *pNotify ) = 0;
+ virtual void RemoveNotificationCallback( IDmNotify *pNotify ) = 0;
+ virtual bool IsSuppressingNotify( ) const = 0;
+ virtual void SetSuppressingNotify( bool bSuppress ) = 0;
+ virtual void PushNotificationScope( const char *pReason, int nNotifySource, int nNotifyFlags ) = 0;
+ virtual void PopNotificationScope( bool bAbort = false ) = 0;
+ virtual const char *GetUndoString( UtlSymId_t sym ) = 0;
+
+ virtual bool HasElementFactory( const char *pElementType ) const = 0;
+
+ // Call before you make any undo records
+ virtual void SetUndoDepth( int nSize ) = 0;
+
+ // Displats memory stats to the console
+ virtual void DisplayMemoryStats() = 0;
+};
+
+
+//-----------------------------------------------------------------------------
+// Used only by applications to hook in the data model
+//-----------------------------------------------------------------------------
+#define VDATAMODEL_INTERFACE_VERSION "VDataModelVersion001"
+
+
+//-----------------------------------------------------------------------------
+// Main interface accessor
+//-----------------------------------------------------------------------------
+extern IDataModel *g_pDataModel;
+
+
+//-----------------------------------------------------------------------------
+// Allows clients to implement customized undo elements
+//-----------------------------------------------------------------------------
+class CUndoElement : public IUndoElement
+{
+public:
+ CUndoElement( const char *pDesc )
+ {
+ m_UndoDesc = g_pDataModel->GetUndoDescInternal( pDesc );
+ m_RedoDesc = g_pDataModel->GetRedoDescInternal( pDesc );
+ m_pDesc = pDesc;
+ m_bEndOfStream = false;
+ }
+
+ virtual void Release()
+ {
+ delete this;
+ }
+
+ virtual const char *UndoDesc() const
+ {
+ return g_pDataModel->GetUndoString( m_UndoDesc );
+ }
+
+ virtual const char *RedoDesc() const
+ {
+ return g_pDataModel->GetUndoString( m_RedoDesc );
+ }
+
+ virtual const char *GetDesc() const
+ {
+ return m_pDesc;
+ }
+
+protected:
+ virtual bool IsEndOfStream() const
+ {
+ return m_bEndOfStream;
+ }
+
+ virtual void SetEndOfStream( bool end )
+ {
+ m_bEndOfStream = end;
+ }
+
+ const char *m_pDesc;
+ CUtlSymbol m_UndoDesc;
+ CUtlSymbol m_RedoDesc;
+ bool m_bEndOfStream;
+
+private:
+ friend class CUndoManager;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Simple helper class
+//-----------------------------------------------------------------------------
+class CUndoScopeGuard
+{
+public:
+ explicit CUndoScopeGuard( const char *udesc, const char *rdesc = NULL )
+ {
+ m_bReleased = false;
+ m_bNotify = false;
+ m_pNotify = NULL;
+ g_pDataModel->StartUndo( udesc, rdesc ? rdesc : udesc );
+ }
+
+ explicit CUndoScopeGuard( int nChainingID, char const *udesc )
+ {
+ m_bReleased = false;
+ m_bNotify = false;
+ m_pNotify = NULL;
+ g_pDataModel->StartUndo( udesc, udesc, nChainingID );
+ }
+
+ explicit CUndoScopeGuard( int nNotifySource, int nNotifyFlags, const char *udesc, const char *rdesc = NULL, int nChainingID = 0 )
+ {
+ m_bReleased = false;
+ m_bNotify = true;
+ m_pNotify = NULL;
+ g_pDataModel->StartUndo( udesc, rdesc ? rdesc : udesc, nChainingID );
+ g_pDataModel->PushNotificationScope( udesc, nNotifySource, nNotifyFlags );
+ }
+
+ explicit CUndoScopeGuard( int nNotifySource, int nNotifyFlags, IDmNotify *pNotify, const char *udesc, const char *rdesc = NULL, int nChainingID = 0 )
+ {
+ m_bReleased = false;
+ m_bNotify = true;
+ m_pNotify = NULL;
+ g_pDataModel->StartUndo( udesc, rdesc ? rdesc : udesc, nChainingID );
+ if ( pNotify )
+ {
+ if ( g_pDataModel->InstallNotificationCallback( pNotify ) )
+ {
+ m_pNotify = pNotify;
+ }
+ }
+ g_pDataModel->PushNotificationScope( udesc, nNotifySource, nNotifyFlags );
+ }
+
+ ~CUndoScopeGuard()
+ {
+ Release();
+ }
+
+ void Release()
+ {
+ if ( !m_bReleased )
+ {
+ g_pDataModel->FinishUndo();
+ if ( m_bNotify )
+ {
+ g_pDataModel->PopNotificationScope( );
+ m_bNotify = false;
+ }
+ if ( m_pNotify )
+ {
+ g_pDataModel->RemoveNotificationCallback( m_pNotify );
+ m_pNotify = NULL;
+ }
+ m_bReleased = true;
+ }
+ }
+
+ void Abort()
+ {
+ if ( !m_bReleased )
+ {
+ g_pDataModel->AbortUndoableOperation();
+ if ( m_bNotify )
+ {
+ g_pDataModel->PopNotificationScope( true );
+ m_bNotify = false;
+ }
+ if ( m_pNotify )
+ {
+ g_pDataModel->RemoveNotificationCallback( m_pNotify );
+ m_pNotify = NULL;
+ }
+ m_bReleased = true;
+ }
+ }
+
+private:
+ IDmNotify *m_pNotify;
+ bool m_bReleased;
+ bool m_bNotify;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Simple helper class to disable Undo/Redo operations when in scope
+//-----------------------------------------------------------------------------
+class CChangeUndoScopeGuard
+{
+public:
+ CChangeUndoScopeGuard( bool bNewState )
+ {
+ m_bReleased = false;
+ m_bNotify = false;
+ m_pNotify = NULL;
+ m_bOldValue = g_pDataModel->IsUndoEnabled();
+ g_pDataModel->SetUndoEnabled( bNewState );
+ };
+
+ CChangeUndoScopeGuard( bool bNewState, const char *pDesc, int nNotifySource, int nNotifyFlags, IDmNotify *pNotify = NULL )
+ {
+ m_bReleased = false;
+ m_bOldValue = g_pDataModel->IsUndoEnabled();
+ g_pDataModel->SetUndoEnabled( bNewState );
+
+ m_bNotify = true;
+ m_pNotify = NULL;
+ if ( pNotify )
+ {
+ if ( g_pDataModel->InstallNotificationCallback( pNotify ) )
+ {
+ m_pNotify = pNotify;
+ }
+ }
+ g_pDataModel->PushNotificationScope( pDesc, nNotifySource, nNotifyFlags );
+ };
+
+ ~CChangeUndoScopeGuard()
+ {
+ Release();
+ }
+
+ void Release()
+ {
+ // Releases the guard...
+ if ( !m_bReleased )
+ {
+ g_pDataModel->SetUndoEnabled( m_bOldValue );
+ m_bReleased = true;
+ if ( m_bNotify )
+ {
+ g_pDataModel->PopNotificationScope( );
+ m_bNotify = false;
+ }
+ if ( m_pNotify )
+ {
+ g_pDataModel->RemoveNotificationCallback( m_pNotify );
+ m_pNotify = NULL;
+ }
+ }
+ }
+
+private:
+ IDmNotify *m_pNotify;
+ bool m_bOldValue;
+ bool m_bReleased;
+ bool m_bNotify;
+};
+
+class CDisableUndoScopeGuard : public CChangeUndoScopeGuard
+{
+ typedef CChangeUndoScopeGuard BaseClass;
+
+public:
+ CDisableUndoScopeGuard() : BaseClass( false ) { }
+ CDisableUndoScopeGuard( const char *pDesc, int nNotifySource, int nNotifyFlags, IDmNotify *pNotify = NULL ) :
+ BaseClass( false, pDesc, nNotifySource, nNotifyFlags, pNotify ) {}
+};
+
+class CEnableUndoScopeGuard : public CChangeUndoScopeGuard
+{
+ typedef CChangeUndoScopeGuard BaseClass;
+
+public:
+ CEnableUndoScopeGuard( ) : BaseClass( true ) { }
+ CEnableUndoScopeGuard( const char *pDesc, int nNotifySource, int nNotifyFlags, IDmNotify *pNotify = NULL ) :
+ BaseClass( true, pDesc, nNotifySource, nNotifyFlags, pNotify ) {}
+};
+
+
+#define DEFINE_SOURCE_UNDO_SCOPE_GUARD( _classnameprefix, _source ) \
+ class C ## _classnameprefix ## UndoScopeGuard : public CUndoScopeGuard \
+ { \
+ typedef CUndoScopeGuard BaseClass; \
+ \
+ public: \
+ C ## _classnameprefix ## UndoScopeGuard( int nNotifyFlags, const char *pUndoDesc, const char *pRedoDesc = NULL, int nChainingID = 0 ) : \
+ BaseClass( _source, nNotifyFlags, pUndoDesc, pRedoDesc, nChainingID ) \
+ { \
+ } \
+ C ## _classnameprefix ## UndoScopeGuard( int nNotifyFlags, IDmNotify *pNotify, const char *pUndoDesc, const char *pRedoDesc = NULL, int nChainingID = 0 ) : \
+ BaseClass( _source, nNotifyFlags, pNotify, pUndoDesc, pRedoDesc, nChainingID ) \
+ { \
+ } \
+ C ## _classnameprefix ## UndoScopeGuard( int nNotifyFlags, const char *pUndoDesc, int nChainingID ) : \
+ BaseClass( _source, nNotifyFlags, pUndoDesc, pUndoDesc, nChainingID ) \
+ { \
+ } \
+ }; \
+ class C ## _classnameprefix ## DisableUndoScopeGuard : public CDisableUndoScopeGuard \
+ { \
+ typedef CDisableUndoScopeGuard BaseClass; \
+ \
+ public: \
+ C ## _classnameprefix ## DisableUndoScopeGuard( const char *pDesc, int nNotifyFlags, IDmNotify *pNotify = NULL ) : \
+ BaseClass( pDesc, _source, nNotifyFlags, pNotify ) \
+ { \
+ } \
+ }; \
+ class C ## _classnameprefix ## EnableUndoScopeGuard : public CEnableUndoScopeGuard \
+ { \
+ typedef CEnableUndoScopeGuard BaseClass; \
+ \
+ public: \
+ C ## _classnameprefix ## EnableUndoScopeGuard( const char *pDesc, int nNotifyFlags, IDmNotify *pNotify = NULL ) : \
+ BaseClass( pDesc, _source, nNotifyFlags, pNotify ) \
+ { \
+ } \
+ }
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Simple helper class to disable NotifyDataChanged from current scope
+//-----------------------------------------------------------------------------
+class CNotifyScopeGuard
+{
+public:
+ CNotifyScopeGuard( const char *pReason, int nNotifySource, int nNotifyFlags, IDmNotify *pNotify = NULL )
+ {
+ m_bReleased = false;
+ m_pNotify = NULL;
+ g_pDataModel->PushNotificationScope( pReason, nNotifySource, nNotifyFlags );
+ if ( pNotify )
+ {
+ if ( g_pDataModel->InstallNotificationCallback( pNotify ) )
+ {
+ m_pNotify = pNotify;
+ }
+ }
+ };
+
+ ~CNotifyScopeGuard()
+ {
+ Release();
+ }
+
+ void Release()
+ {
+ // Releases the guard...
+ if ( !m_bReleased )
+ {
+ g_pDataModel->PopNotificationScope( );
+ if ( m_pNotify )
+ {
+ g_pDataModel->RemoveNotificationCallback( m_pNotify );
+ m_pNotify = NULL;
+ }
+ m_bReleased = true;
+ }
+ }
+
+private:
+ CNotifyScopeGuard( const CNotifyScopeGuard& g );
+
+private:
+ IDmNotify *m_pNotify;
+ bool m_bReleased;
+};
+
+
+#define DEFINE_SOURCE_NOTIFY_SCOPE_GUARD( _classnameprefix, _source ) \
+ class C ## _classnameprefix ## NotifyScopeGuard : public CNotifyScopeGuard \
+ { \
+ typedef CNotifyScopeGuard BaseClass; \
+ \
+ public: \
+ C ## _classnameprefix ## NotifyScopeGuard( const char *pReason, int nNotifyFlags, IDmNotify *pNotify = NULL ) : \
+ BaseClass( pReason, _source, nNotifyFlags, pNotify )\
+ { \
+ } \
+ }
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Simple helper class to disable notifications when in scope
+//-----------------------------------------------------------------------------
+class CChangeNotifyScopeGuard
+{
+public:
+ CChangeNotifyScopeGuard( bool bNewState )
+ {
+ m_bReleased = false;
+ m_bOldValue = g_pDataModel->IsSuppressingNotify();
+ g_pDataModel->SetSuppressingNotify( bNewState );
+ };
+
+ ~CChangeNotifyScopeGuard()
+ {
+ Release();
+ }
+
+ void Release()
+ {
+ // Releases the guard...
+ if ( !m_bReleased )
+ {
+ g_pDataModel->SetSuppressingNotify( m_bOldValue );
+ m_bReleased = true;
+ }
+ }
+
+private:
+ bool m_bOldValue;
+ bool m_bReleased;
+};
+
+class CDisableNotifyScopeGuard : public CChangeNotifyScopeGuard
+{
+ typedef CChangeNotifyScopeGuard BaseClass;
+
+public:
+ CDisableNotifyScopeGuard() : BaseClass( true ) { }
+
+private:
+ CDisableNotifyScopeGuard( const CDisableNotifyScopeGuard& g );
+};
+
+class CEnableNotifyScopeGuard : public CChangeNotifyScopeGuard
+{
+ typedef CChangeNotifyScopeGuard BaseClass;
+
+public:
+ CEnableNotifyScopeGuard( ) : BaseClass( false ) { }
+
+private:
+ CEnableNotifyScopeGuard( const CEnableNotifyScopeGuard& g );
+};
+
+
+//-----------------------------------------------------------------------------
+// Standard undo/notify guards for the application
+//-----------------------------------------------------------------------------
+DEFINE_SOURCE_UNDO_SCOPE_GUARD( App, NOTIFY_SOURCE_APPLICATION );
+DEFINE_SOURCE_NOTIFY_SCOPE_GUARD( App, NOTIFY_SOURCE_APPLICATION );
+
+
+
+#endif // IDATAMODEL_H