diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /public/datamodel | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'public/datamodel')
| -rw-r--r-- | public/datamodel/attributeflags.h | 35 | ||||
| -rw-r--r-- | public/datamodel/dmattribute.h | 768 | ||||
| -rw-r--r-- | public/datamodel/dmattributetypes.h | 317 | ||||
| -rw-r--r-- | public/datamodel/dmattributevar.h | 1481 | ||||
| -rw-r--r-- | public/datamodel/dmehandle.h | 243 | ||||
| -rw-r--r-- | public/datamodel/dmelement.h | 618 | ||||
| -rw-r--r-- | public/datamodel/dmelementfactoryhelper.h | 190 | ||||
| -rw-r--r-- | public/datamodel/dmelementhandle.h | 47 | ||||
| -rw-r--r-- | public/datamodel/dmvar.h | 93 | ||||
| -rw-r--r-- | public/datamodel/idatamodel.h | 938 |
10 files changed, 4730 insertions, 0 deletions
diff --git a/public/datamodel/attributeflags.h b/public/datamodel/attributeflags.h new file mode 100644 index 0000000..8cacdb4 --- /dev/null +++ b/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/public/datamodel/dmattribute.h b/public/datamodel/dmattribute.h new file mode 100644 index 0000000..e383eab --- /dev/null +++ b/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, (int)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, (int)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/public/datamodel/dmattributetypes.h b/public/datamodel/dmattributetypes.h new file mode 100644 index 0000000..3a29caa --- /dev/null +++ b/public/datamodel/dmattributetypes.h @@ -0,0 +1,317 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef DMATTRIBUTETYPES_H +#define DMATTRIBUTETYPES_H +#ifdef _WIN32 +#pragma once +#endif + +#include "tier1/utlvector.h" +#include "tier1/utlbinaryblock.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/public/datamodel/dmattributevar.h b/public/datamodel/dmattributevar.h new file mode 100644 index 0000000..4bf2a23 --- /dev/null +++ b/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/public/datamodel/dmehandle.h b/public/datamodel/dmehandle.h new file mode 100644 index 0000000..f2b7898 --- /dev/null +++ b/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/public/datamodel/dmelement.h b/public/datamodel/dmelement.h new file mode 100644 index 0000000..13a8bec --- /dev/null +++ b/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/public/datamodel/dmelementfactoryhelper.h b/public/datamodel/dmelementfactoryhelper.h new file mode 100644 index 0000000..c4847cc --- /dev/null +++ b/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/public/datamodel/dmelementhandle.h b/public/datamodel/dmelementhandle.h new file mode 100644 index 0000000..319f308 --- /dev/null +++ b/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/public/datamodel/dmvar.h b/public/datamodel/dmvar.h new file mode 100644 index 0000000..940e138 --- /dev/null +++ b/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/public/datamodel/idatamodel.h b/public/datamodel/idatamodel.h new file mode 100644 index 0000000..16f2c73 --- /dev/null +++ b/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 |