1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-09-19 03:56:10 +08:00

First version of the SOurce SDK 2013

This commit is contained in:
Joe Ludwig
2013-06-26 15:22:04 -07:00
commit e7d6f4c174
3682 changed files with 1624327 additions and 0 deletions

View File

@ -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

View File

@ -0,0 +1,768 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef DMATTRIBUTE_H
#define DMATTRIBUTE_H
#ifdef _WIN32
#pragma once
#endif
#include "datamodel/attributeflags.h"
#include "datamodel/idatamodel.h"
#include "datamodel/dmattributetypes.h"
#include "datamodel/dmelement.h"
#include "datamodel/dmvar.h"
#include "tier1/utlhash.h"
//-----------------------------------------------------------------------------
// Fast dynamic cast
//-----------------------------------------------------------------------------
template< class E >
inline E *CastElement( CDmElement *pElement )
{
if ( pElement && pElement->IsA( E::GetStaticTypeSymbol() ) )
return static_cast< E* >( pElement );
return NULL;
}
//-----------------------------------------------------------------------------
// type-safe element creation and accessor helpers - infers type name string from actual type
//-----------------------------------------------------------------------------
template< class E >
inline E *GetElement( DmElementHandle_t hElement )
{
CDmElement *pElement = g_pDataModel->GetElement( hElement );
return CastElement< E >( pElement );
}
//-----------------------------------------------------------------------------
// Typesafe element creation + destruction
//-----------------------------------------------------------------------------
template< class E >
inline E *CreateElement( const char *pObjectName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL )
{
return GetElement< E >( g_pDataModel->CreateElement( E::GetStaticTypeSymbol(), pObjectName, fileid, pObjectID ) );
}
template< class E >
inline E *CreateElement( const char *pElementType, const char *pObjectName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL )
{
return GetElement< E >( g_pDataModel->CreateElement( pElementType, pObjectName, fileid, pObjectID ) );
}
//-----------------------------------------------------------------------------
// Used for attribute change callbacks
//-----------------------------------------------------------------------------
typedef unsigned short DmMailingList_t;
enum
{
DMMAILINGLIST_INVALID = (DmMailingList_t)~0
};
//-----------------------------------------------------------------------------
// Purpose: A general purpose pAttribute. Eventually will be extensible to arbitrary user types
//-----------------------------------------------------------------------------
class CDmAttribute
{
public:
// Returns the type
DmAttributeType_t GetType() const;
const char *GetTypeString() const;
template< class T > bool IsA() const;
// Returns the name. NOTE: The utlsymbol
// can be turned into a string by using g_pDataModel->String();
const char *GetName() const;
UtlSymId_t GetNameSymbol() const;
void SetName( const char *newName );
// Gets the attribute value
// NOTE: GetValueUntyped is used with GetType() for use w/ SetValue( type, void* )
template< class T > const T& GetValue() const;
template< class T > const T& GetValue( const T& defaultValue ) const;
const char *GetValueString() const;
template< class E > E *GetValueElement() const;
const void *GetValueUntyped() const;
// Sets the attribute value
template< class T > void SetValue( const T &value );
template< class E > void SetValue( E* pValue );
void SetValue( const void *pValue, size_t nSize );
// Copies w/ type conversion (if possible) from another attribute
void SetValue( const CDmAttribute *pAttribute );
void SetValue( CDmAttribute *pAttribute );
void SetValue( DmAttributeType_t valueType, const void *pValue );
// Sets the attribute to its default value based on its type
void SetToDefaultValue();
// Convert to and from string
void SetValueFromString( const char *pValue );
const char *GetValueAsString( char *pBuffer, size_t nBufLen ) const;
// Used for element and element array attributes; it specifies which type of
// elements are valid to be referred to by this attribute
void SetElementTypeSymbol( UtlSymId_t typeSymbol );
UtlSymId_t GetElementTypeSymbol() const;
// Returns the next attribute
CDmAttribute *NextAttribute();
const CDmAttribute *NextAttribute() const;
// Returns the owner
CDmElement *GetOwner();
// Methods related to flags
void AddFlag( int flags );
void RemoveFlag( int flags );
void ClearFlags();
int GetFlags() const;
bool IsFlagSet( int flags ) const;
// Serialization
bool Serialize( CUtlBuffer &buf ) const;
bool Unserialize( CUtlBuffer &buf );
// Serialization of a single element.
// First version of UnserializeElement adds to tail if it worked
// Second version overwrites, but does not add, the element at the specified index
bool SerializeElement( int nElement, CUtlBuffer &buf ) const;
bool UnserializeElement( CUtlBuffer &buf );
bool UnserializeElement( int nElement, CUtlBuffer &buf );
// Does this attribute serialize on multiple lines?
bool SerializesOnMultipleLines() const;
// Get the attribute/create an attribute handle
DmAttributeHandle_t GetHandle( bool bCreate = true );
// Notify external elements upon change ( Calls OnAttributeChanged )
// Pass false here to stop notification
void NotifyWhenChanged( DmElementHandle_t h, bool bNotify );
// estimate memory overhead
int EstimateMemoryUsage( TraversalDepth_t depth ) const;
private:
// Class factory
static CDmAttribute *CreateAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName );
static CDmAttribute *CreateExternalAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName, void *pExternalMemory );
static void DestroyAttribute( CDmAttribute *pAttribute );
// Constructor, destructor
CDmAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName );
CDmAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName, void *pMemory );
~CDmAttribute();
// Used when constructing CDmAttributes
void Init( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName );
// Used when shutting down, indicates DmAttributeHandle_t referring to this are invalid
void InvalidateHandle();
// Used when shutting down, indicates no more change notifications will be sent to listening elements
void CleanupMailingList();
// Called when the attribute changes
void PreChanged();
void OnChanged( bool bArrayCountChanged = false, bool bIsTopological = false );
// Is modification allowed in this phase?
bool ModificationAllowed() const;
// Mark the attribute as being dirty
bool MarkDirty();
// Is the data inline in a containing element class?
bool IsDataInline() const;
// Allocates, frees internal data storage
void CreateAttributeData();
void DeleteAttributeData();
// Gets at the internal data storage
void* GetAttributeData();
const void* GetAttributeData() const;
template < class T > typename CDmAttributeInfo< T >::StorageType_t* GetData();
template < class T > const typename CDmAttributeInfo< T >::StorageType_t* GetData() const;
template < class T > typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* GetArrayData();
template < class T > const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* GetArrayData() const;
// Used by CDmElement to manage the list of attributes it owns
CDmAttribute **GetNextAttributeRef();
// Implementational function used for memory consumption estimation computation
int EstimateMemoryUsageInternal( CUtlHash< DmElementHandle_t > &visited, TraversalDepth_t depth, int *pCategories ) const;
// Called by elements after unserialization of their attributes is complete
void OnUnserializationFinished();
template< class T > bool IsTypeConvertable() const;
template< class T > bool ShouldModify( const T& src );
template< class T > void CopyData( const T& src );
template< class T > void CopyDataOut( T& dest ) const;
private:
CDmAttribute *m_pNext;
void *m_pData;
CDmElement *m_pOwner;
int m_nFlags;
DmAttributeHandle_t m_Handle;
CUtlSymbol m_Name;
DmMailingList_t m_hMailingList;
friend class CDmElement;
friend class CDmAttributeAccessor;
template< class T > friend class CDmrElementArray;
template< class E > friend class CDmrElementArrayConst;
template< class T > friend class CDmaArrayAccessor;
template< class T, class B > friend class CDmrDecorator;
template< class T, class B > friend class CDmrDecoratorConst;
template< class T > friend class CDmArrayAttributeOp;
};
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline DmAttributeType_t CDmAttribute::GetType() const
{
return (DmAttributeType_t)( m_nFlags & FATTRIB_TYPEMASK );
}
template< class T > inline bool CDmAttribute::IsA() const
{
return GetType() == CDmAttributeInfo< T >::AttributeType();
}
inline const char *CDmAttribute::GetName() const
{
return g_pDataModel->GetString( m_Name );
}
inline UtlSymId_t CDmAttribute::GetNameSymbol() const
{
return m_Name;
}
//-----------------------------------------------------------------------------
// Iteration
//-----------------------------------------------------------------------------
inline CDmAttribute *CDmAttribute::NextAttribute()
{
return m_pNext;
}
inline const CDmAttribute *CDmAttribute::NextAttribute() const
{
return m_pNext;
}
//-----------------------------------------------------------------------------
// Returns the owner
//-----------------------------------------------------------------------------
inline CDmElement *CDmAttribute::GetOwner()
{
return m_pOwner;
}
//-----------------------------------------------------------------------------
// Value getting methods
//-----------------------------------------------------------------------------
template< class T >
inline const T& CDmAttribute::GetValue( const T& defaultValue ) const
{
if ( GetType() == ( DmAttributeType_t )( CDmAttributeInfo< T >::ATTRIBUTE_TYPE ) )
return *reinterpret_cast< const T* >( m_pData );
if ( IsTypeConvertable< T >() )
{
static T tempVal;
CopyDataOut( tempVal );
return tempVal;
}
Assert( 0 );
return defaultValue;
}
template< class T >
inline const T& CDmAttribute::GetValue() const
{
static CDmaVar< T > defaultVal;
return GetValue( defaultVal.Get() );
}
inline const char *CDmAttribute::GetValueString() const
{
Assert( GetType() == AT_STRING );
if ( GetType() != AT_STRING )
return NULL;
return GetValue< CUtlString >();
}
// used with GetType() for use w/ SetValue( type, void* )
inline const void* CDmAttribute::GetValueUntyped() const
{
return m_pData;
}
template< class E >
inline E* CDmAttribute::GetValueElement() const
{
Assert( GetType() == AT_ELEMENT );
if ( GetType() == AT_ELEMENT )
return GetElement<E>( this->GetValue< DmElementHandle_t >() );
return NULL;
}
//-----------------------------------------------------------------------------
// Value setting methods
//-----------------------------------------------------------------------------
template< class E >
inline void CDmAttribute::SetValue( E* pValue )
{
Assert( GetType() == AT_ELEMENT );
if ( GetType() == AT_ELEMENT )
{
SetValue( pValue ? pValue->GetHandle() : DMELEMENT_HANDLE_INVALID );
}
}
template<>
inline void CDmAttribute::SetValue( const char *pValue )
{
int nLen = pValue ? Q_strlen( pValue ) + 1 : 0;
CUtlString str( pValue, nLen );
return SetValue( str );
}
template<>
inline void CDmAttribute::SetValue( char *pValue )
{
return SetValue( (const char *)pValue );
}
inline void CDmAttribute::SetValue( const void *pValue, size_t nSize )
{
CUtlBinaryBlock buf( pValue, nSize );
return SetValue( buf );
}
//-----------------------------------------------------------------------------
// Methods related to flags
//-----------------------------------------------------------------------------
inline void CDmAttribute::AddFlag( int nFlags )
{
m_nFlags |= nFlags;
}
inline void CDmAttribute::RemoveFlag( int nFlags )
{
m_nFlags &= ~nFlags;
}
inline void CDmAttribute::ClearFlags()
{
m_nFlags = 0;
}
inline int CDmAttribute::GetFlags() const
{
return m_nFlags;
}
inline bool CDmAttribute::IsFlagSet( int nFlags ) const
{
return ( nFlags & m_nFlags ) ? true : false;
}
inline bool CDmAttribute::IsDataInline() const
{
return !IsFlagSet(FATTRIB_EXTERNAL);
}
//-----------------------------------------------------------------------------
// Gets at the internal data storage
//-----------------------------------------------------------------------------
inline void* CDmAttribute::GetAttributeData()
{
return m_pData;
}
inline const void* CDmAttribute::GetAttributeData() const
{
return m_pData;
}
template < class T >
inline typename CDmAttributeInfo< T >::StorageType_t* CDmAttribute::GetData()
{
return ( typename CDmAttributeInfo< T >::StorageType_t* )m_pData;
}
template < class T >
inline typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* CDmAttribute::GetArrayData()
{
return ( typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* )m_pData;
}
template < class T >
inline const typename CDmAttributeInfo< T >::StorageType_t* CDmAttribute::GetData() const
{
return ( const typename CDmAttributeInfo< T >::StorageType_t* )m_pData;
}
template < class T >
inline const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* CDmAttribute::GetArrayData() const
{
return ( const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* )m_pData;
}
//-----------------------------------------------------------------------------
// Used by CDmElement to manage the list of attributes it owns
//-----------------------------------------------------------------------------
inline CDmAttribute **CDmAttribute::GetNextAttributeRef()
{
return &m_pNext;
}
//-----------------------------------------------------------------------------
// helper function for determining which attributes/elements to traverse during copy/find/save/etc.
//-----------------------------------------------------------------------------
inline bool ShouldTraverse( const CDmAttribute *pAttr, TraversalDepth_t depth )
{
switch ( depth )
{
case TD_NONE:
return false;
case TD_SHALLOW:
if ( !pAttr->IsFlagSet( FATTRIB_MUSTCOPY ) )
return false;
// fall-through intentional
case TD_DEEP:
if ( pAttr->IsFlagSet( FATTRIB_NEVERCOPY ) )
return false;
// fall-through intentional
case TD_ALL:
return true;
}
Assert( 0 );
return false;
}
//-----------------------------------------------------------------------------
// Gets attributes
//-----------------------------------------------------------------------------
inline CDmAttribute *CDmElement::GetAttribute( const char *pAttributeName, DmAttributeType_t type )
{
CDmAttribute *pAttribute = FindAttribute( pAttributeName );
if ( ( type != AT_UNKNOWN ) && pAttribute && ( pAttribute->GetType() != type ) )
return NULL;
return pAttribute;
}
inline const CDmAttribute *CDmElement::GetAttribute( const char *pAttributeName, DmAttributeType_t type ) const
{
CDmAttribute *pAttribute = FindAttribute( pAttributeName );
if ( ( type != AT_UNKNOWN ) && pAttribute && ( pAttribute->GetType() != type ) )
return NULL;
return pAttribute;
}
//-----------------------------------------------------------------------------
// AddAttribute calls
//-----------------------------------------------------------------------------
inline CDmAttribute *CDmElement::AddAttribute( const char *pAttributeName, DmAttributeType_t type )
{
CDmAttribute *pAttribute = FindAttribute( pAttributeName );
if ( pAttribute )
return ( pAttribute->GetType() == type ) ? pAttribute : NULL;
pAttribute = CreateAttribute( pAttributeName, type );
return pAttribute;
}
template< class E > inline CDmAttribute *CDmElement::AddAttributeElement( const char *pAttributeName )
{
CDmAttribute *pAttribute = AddAttribute( pAttributeName, AT_ELEMENT );
if ( !pAttribute )
return NULL;
// FIXME: If the attribute exists but has a different element type symbol, should we complain?
pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() );
return pAttribute;
}
template< class E > inline CDmAttribute *CDmElement::AddAttributeElementArray( const char *pAttributeName )
{
CDmAttribute *pAttribute = AddAttribute( pAttributeName, AT_ELEMENT_ARRAY );
if ( !pAttribute )
return NULL;
// FIXME: If the attribute exists but has a different element type symbol, should we complain?
pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() );
return pAttribute;
}
//-----------------------------------------------------------------------------
// GetValue methods
//-----------------------------------------------------------------------------
template< class T >
inline const T& CDmElement::GetValue( const char *pAttributeName ) const
{
static CDmaVar<T> defaultVal;
return GetValue( pAttributeName, defaultVal.Get() );
}
inline const char *CDmElement::GetValueString( const char *pAttributeName ) const
{
return GetValue<CUtlString>( pAttributeName ).Get();
}
template< class E >
inline E* CDmElement::GetValueElement( const char *pAttributeName ) const
{
DmElementHandle_t h = GetValue< DmElementHandle_t >( pAttributeName );
return GetElement<E>( h );
}
template< class T >
inline const T& CDmElement::GetValue( const char *pAttributeName, const T& defaultVal ) const
{
const CDmAttribute *pAttribute = FindAttribute( pAttributeName );
if ( pAttribute != NULL )
return pAttribute->GetValue<T>();
return defaultVal;
}
//-----------------------------------------------------------------------------
// SetValue methods
//-----------------------------------------------------------------------------
template< class T >
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const T& value )
{
CDmAttribute *pAttribute = FindAttribute( pAttributeName );
if ( !pAttribute )
{
pAttribute = CreateAttribute( pAttributeName, CDmAttributeInfo<T>::AttributeType() );
}
if ( pAttribute )
{
pAttribute->SetValue( value );
return pAttribute;
}
return NULL;
}
template< class E >
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, E* pElement )
{
DmElementHandle_t hElement = pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID;
return SetValue( pAttributeName, hElement );
}
template<>
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const char *pValue )
{
int nLen = pValue ? Q_strlen( pValue ) + 1 : 0;
CUtlString str( pValue, nLen );
return SetValue( pAttributeName, str );
}
template<>
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, char *pValue )
{
return SetValue( pAttributeName, (const char *)pValue );
}
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const void *pValue, size_t nSize )
{
CUtlBinaryBlock buf( pValue, nSize );
return SetValue( pAttributeName, buf );
}
//-----------------------------------------------------------------------------
// AddValue methods( set value if not found )
//-----------------------------------------------------------------------------
template< class T >
inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, const T& value )
{
CDmAttribute *pAttribute = GetAttribute( pAttributeName );
if ( !pAttribute )
return SetValue( pAttributeName, value );
return pAttribute;
}
template< class E >
inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, E* pElement )
{
DmElementHandle_t hElement = pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID;
return InitValue( pAttributeName, hElement );
}
inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, const void *pValue, size_t size )
{
CDmAttribute *pAttribute = GetAttribute( pAttributeName );
if ( !pAttribute )
return SetValue( pAttributeName, pValue, size );
return pAttribute;
}
template< class T >
T *FindReferringElement( CDmElement *pElement, UtlSymId_t symAttrName, bool bMustBeInSameFile = true )
{
DmAttributeReferenceIterator_t i = g_pDataModel->FirstAttributeReferencingElement( pElement->GetHandle() );
while ( i != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID )
{
CDmAttribute *pAttribute = g_pDataModel->GetAttribute( i );
CDmElement *pDmeParent = pAttribute->GetOwner();
if ( pDmeParent && pAttribute->GetNameSymbol() == symAttrName )
{
T *pParent = CastElement< T >( pDmeParent );
if ( pParent )
{
if ( !bMustBeInSameFile || ( pParent->GetFileId() == pElement->GetFileId() ) )
return pParent;
}
}
i = g_pDataModel->NextAttributeReferencingElement( i );
}
return NULL;
}
template< class T >
T *FindAncestorReferencingElement( CDmElement *target )
{
if ( !target )
return NULL;
for ( DmAttributeReferenceIterator_t it = g_pDataModel->FirstAttributeReferencingElement( target->GetHandle() );
it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
it = g_pDataModel->NextAttributeReferencingElement( it ) )
{
CDmAttribute *attr = g_pDataModel->GetAttribute( it );
Assert( attr );
CDmElement *element = attr->GetOwner();
Assert( element );
if ( !element )
continue;
T *t = CastElement< T >( element );
if ( !t )
continue;
return t;
}
return NULL;
}
template< class T >
T *FindAncestorReferencingElement_R_Impl( CUtlRBTree< CDmElement * >& visited, CDmElement *check )
{
if ( visited.Find( check ) != visited.InvalidIndex() )
return NULL;
visited.Insert( check );
// Pass one, see if it's in this ancestor list
DmAttributeReferenceIterator_t it;
for ( it = g_pDataModel->FirstAttributeReferencingElement( check->GetHandle() );
it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
it = g_pDataModel->NextAttributeReferencingElement( it ) )
{
CDmAttribute *attr = g_pDataModel->GetAttribute( it );
Assert( attr );
CDmElement *element = attr->GetOwner();
Assert( element );
if ( !element )
continue;
T *t = CastElement< T >( element );
if ( !t )
continue;
return t;
}
for ( it = g_pDataModel->FirstAttributeReferencingElement( check->GetHandle() );
it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
it = g_pDataModel->NextAttributeReferencingElement( it ) )
{
CDmAttribute *attr = g_pDataModel->GetAttribute( it );
Assert( attr );
CDmElement *element = attr->GetOwner();
Assert( element );
if ( !element )
continue;
T *found = FindAncestorReferencingElement_R_Impl< T >( visited, element );
if ( found )
return found;
}
return NULL;
}
template< class T >
void FindAncestorsReferencingElement( CDmElement *target, CUtlVector< T* >& list )
{
if ( !target )
return;
list.RemoveAll();
for ( DmAttributeReferenceIterator_t it = g_pDataModel->FirstAttributeReferencingElement( target->GetHandle() );
it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
it = g_pDataModel->NextAttributeReferencingElement( it ) )
{
CDmAttribute *attr = g_pDataModel->GetAttribute( it );
Assert( attr );
CDmElement *element = attr->GetOwner();
Assert( element );
if ( !element )
continue;
T* t = CastElement< T >( element );
if ( !t )
continue;
if ( list.Find( t ) != list.InvalidIndex() )
continue;
list.AddToTail( t );
}
}
template< class T >
T *FindAncestorReferencingElement_R( CDmElement *target )
{
if ( !target )
return NULL;
CUtlRBTree< CDmElement * > visited( 0, 0, DefLessFunc( CDmElement * ) );
return FindAncestorReferencingElement_R_Impl< T >( visited, target );
}
#endif // DMATTRIBUTE_H

View File

@ -0,0 +1,316 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef DMATTRIBUTETYPES_H
#define DMATTRIBUTETYPES_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utlvector.h"
#include "tier1/utlstring.h"
#include "tier1/uniqueid.h"
#include "Color.h"
#include "mathlib/vector2d.h"
#include "mathlib/vector.h"
#include "mathlib/vector4d.h"
#include "mathlib/vmatrix.h"
#include "datamodel/dmelementhandle.h"
#include "tier1/utlsymbol.h"
//-----------------------------------------------------------------------------
// Object Id
//-----------------------------------------------------------------------------
typedef UniqueId_t DmObjectId_t;
//-----------------------------------------------------------------------------
// Necessary for template specialization for AT_UNKNOWN
//-----------------------------------------------------------------------------
struct DmUnknownAttribute_t
{
bool operator==( const DmUnknownAttribute_t& src ) const { return true; }
};
//-----------------------------------------------------------------------------
// Element array
//-----------------------------------------------------------------------------
struct DmElementAttribute_t
{
DmElementAttribute_t() : m_ElementType( UTL_INVAL_SYMBOL ) {}
operator DmElementHandle_t&() { return m_Handle; }
operator const DmElementHandle_t&() const { return m_Handle; }
DmElementHandle_t m_Handle;
UtlSymId_t m_ElementType;
};
struct DmElementArray_t : public CUtlVector< DmElementHandle_t >
{
DmElementArray_t() : m_ElementType( UTL_INVAL_SYMBOL ) {}
UtlSymId_t m_ElementType;
};
//-----------------------------------------------------------------------------
// Attribute chunk type enum
//-----------------------------------------------------------------------------
enum DmAttributeType_t
{
AT_UNKNOWN = 0,
AT_FIRST_VALUE_TYPE,
AT_ELEMENT = AT_FIRST_VALUE_TYPE,
AT_INT,
AT_FLOAT,
AT_BOOL,
AT_STRING,
AT_VOID,
AT_OBJECTID,
AT_COLOR, //rgba
AT_VECTOR2,
AT_VECTOR3,
AT_VECTOR4,
AT_QANGLE,
AT_QUATERNION,
AT_VMATRIX,
AT_FIRST_ARRAY_TYPE,
AT_ELEMENT_ARRAY = AT_FIRST_ARRAY_TYPE,
AT_INT_ARRAY,
AT_FLOAT_ARRAY,
AT_BOOL_ARRAY,
AT_STRING_ARRAY,
AT_VOID_ARRAY,
AT_OBJECTID_ARRAY,
AT_COLOR_ARRAY,
AT_VECTOR2_ARRAY,
AT_VECTOR3_ARRAY,
AT_VECTOR4_ARRAY,
AT_QANGLE_ARRAY,
AT_QUATERNION_ARRAY,
AT_VMATRIX_ARRAY,
AT_TYPE_COUNT,
};
const char *GetTypeString( DmAttributeType_t type );
inline bool IsValueType( DmAttributeType_t type )
{
return type >= AT_FIRST_VALUE_TYPE && type < AT_FIRST_ARRAY_TYPE;
}
inline bool IsArrayType( DmAttributeType_t type )
{
return type >= AT_FIRST_ARRAY_TYPE && type < AT_TYPE_COUNT;
}
inline bool IsTopological( DmAttributeType_t type )
{
return type == AT_ELEMENT || type == AT_ELEMENT_ARRAY;
}
inline DmAttributeType_t ValueTypeToArrayType( DmAttributeType_t type )
{
Assert( IsValueType( type ) );
return ( DmAttributeType_t )( ( type - AT_FIRST_VALUE_TYPE ) + AT_FIRST_ARRAY_TYPE );
}
inline DmAttributeType_t ArrayTypeToValueType( DmAttributeType_t type )
{
Assert( IsArrayType( type ) );
return ( DmAttributeType_t )( ( type - AT_FIRST_ARRAY_TYPE ) + AT_FIRST_VALUE_TYPE );
}
inline int NumComponents( DmAttributeType_t type )
{
switch ( type )
{
case AT_BOOL:
case AT_INT:
case AT_FLOAT:
return 1;
case AT_VECTOR2:
return 2;
case AT_VECTOR3:
case AT_QANGLE:
return 3;
case AT_COLOR: //rgba
case AT_VECTOR4:
case AT_QUATERNION:
return 4;
case AT_VMATRIX:
return 16;
case AT_ELEMENT:
case AT_STRING:
case AT_VOID:
case AT_OBJECTID:
default:
return 0;
}
}
template< typename T >
inline float GetComponent( const T &value, int i )
{
Assert( 0 );
return 0.0f;
}
template <> inline float GetComponent( const bool &value, int i )
{
Assert( i == 0 );
return value ? 1.0f : 0.0f;
}
template <> inline float GetComponent( const int &value, int i )
{
Assert( i == 0 );
return float( value );
}
template <> inline float GetComponent( const float &value, int i )
{
Assert( i == 0 );
return value;
}
template <> inline float GetComponent( const Vector2D &value, int i )
{
return value[ i ];
}
template <> inline float GetComponent( const Vector &value, int i )
{
return value[ i ];
}
template <> inline float GetComponent( const QAngle &value, int i )
{
return value[ i ];
}
template <> inline float GetComponent( const Color &value, int i )
{
return value[ i ];
}
template <> inline float GetComponent( const Vector4D &value, int i )
{
return value[ i ];
}
template <> inline float GetComponent( const Quaternion &value, int i )
{
return value[ i ];
}
template <> inline float GetComponent( const VMatrix &value, int i )
{
return value.Base()[ i ];
}
//-----------------------------------------------------------------------------
// Attribute info...
//-----------------------------------------------------------------------------
template <typename T>
class CDmAttributeInfo
{
public:
enum { ATTRIBUTE_TYPE = AT_UNKNOWN };
typedef T StorageType_t;
static DmAttributeType_t AttributeType()
{
return AT_UNKNOWN;
}
static const char *AttributeTypeName()
{
return "unknown";
}
static void SetDefaultValue( T& value )
{
Assert(0);
}
};
#define DECLARE_ATTRIBUTE_TYPE_INTERNAL( _className, _storageType, _attributeType, _attributeName, _defaultSetStatement ) \
template< > class CDmAttributeInfo< _className > \
{ \
public: \
enum { ATTRIBUTE_TYPE = _attributeType }; \
typedef _storageType StorageType_t; \
static DmAttributeType_t AttributeType() { return _attributeType; } \
static const char *AttributeTypeName() { return _attributeName; } \
static void SetDefaultValue( _className& value ) { _defaultSetStatement } \
}; \
#define DECLARE_ATTRIBUTE_ARRAY_TYPE_INTERNAL( _className, _storageType, _attributeType, _attributeName ) \
template< > class CDmAttributeInfo< CUtlVector<_className> > \
{ \
public: \
enum { ATTRIBUTE_TYPE = _attributeType }; \
typedef _storageType StorageType_t; \
static DmAttributeType_t AttributeType() { return _attributeType; } \
static const char *AttributeTypeName() { return _attributeName; } \
static void SetDefaultValue( CUtlVector< _className >& value ) { value.RemoveAll(); } \
}; \
#define DECLARE_ATTRIBUTE_TYPE( _className, _attributeType, _attributeName, _defaultSetStatement ) \
DECLARE_ATTRIBUTE_TYPE_INTERNAL( _className, _className, _attributeType, _attributeName, _defaultSetStatement )
#define DECLARE_ATTRIBUTE_ARRAY_TYPE( _className, _attributeType, _attributeName )\
DECLARE_ATTRIBUTE_ARRAY_TYPE_INTERNAL( _className, CUtlVector< _className >, _attributeType, _attributeName )
// NOTE: If you add an attribute type here, also add it to the list of DEFINE_ATTRIBUTE_TYPES in dmattribute.cpp
DECLARE_ATTRIBUTE_TYPE( int, AT_INT, "int", value = 0; )
DECLARE_ATTRIBUTE_TYPE( float, AT_FLOAT, "float", value = 0.0f; )
DECLARE_ATTRIBUTE_TYPE( bool, AT_BOOL, "bool", value = false; )
DECLARE_ATTRIBUTE_TYPE( Color, AT_COLOR, "color", value.SetColor( 0, 0, 0, 255 ); )
DECLARE_ATTRIBUTE_TYPE( Vector2D, AT_VECTOR2, "vector2", value.Init( 0.0f, 0.0f ); )
DECLARE_ATTRIBUTE_TYPE( Vector, AT_VECTOR3, "vector3", value.Init( 0.0f, 0.0f, 0.0f ); )
DECLARE_ATTRIBUTE_TYPE( Vector4D, AT_VECTOR4, "vector4", value.Init( 0.0f, 0.0f, 0.0f, 0.0f ); )
DECLARE_ATTRIBUTE_TYPE( QAngle, AT_QANGLE, "qangle", value.Init( 0.0f, 0.0f, 0.0f ); )
DECLARE_ATTRIBUTE_TYPE( Quaternion, AT_QUATERNION, "quaternion", value.Init( 0.0f, 0.0f, 0.0f, 1.0f ); )
DECLARE_ATTRIBUTE_TYPE( VMatrix, AT_VMATRIX, "matrix", MatrixSetIdentity( value ); )
DECLARE_ATTRIBUTE_TYPE( CUtlString, AT_STRING, "string", value.Set( NULL ); )
DECLARE_ATTRIBUTE_TYPE( CUtlBinaryBlock, AT_VOID, "binary", value.Set( NULL, 0 ); )
DECLARE_ATTRIBUTE_TYPE( DmObjectId_t, AT_OBJECTID, "elementid", InvalidateUniqueId( &value ); )
DECLARE_ATTRIBUTE_TYPE_INTERNAL( DmElementHandle_t, DmElementAttribute_t, AT_ELEMENT, "element", value = DMELEMENT_HANDLE_INVALID; )
DECLARE_ATTRIBUTE_ARRAY_TYPE( int, AT_INT_ARRAY, "int_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( float, AT_FLOAT_ARRAY, "float_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( bool, AT_BOOL_ARRAY, "bool_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( Color, AT_COLOR_ARRAY, "color_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( Vector2D, AT_VECTOR2_ARRAY, "vector2_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( Vector, AT_VECTOR3_ARRAY, "vector3_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( Vector4D, AT_VECTOR4_ARRAY, "vector4_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( QAngle, AT_QANGLE_ARRAY, "qangle_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( Quaternion, AT_QUATERNION_ARRAY, "quaternion_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( VMatrix, AT_VMATRIX_ARRAY, "matrix_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( CUtlString, AT_STRING_ARRAY, "string_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( CUtlBinaryBlock, AT_VOID_ARRAY, "binary_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( DmObjectId_t, AT_OBJECTID_ARRAY, "elementid_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE_INTERNAL( DmElementHandle_t, DmElementArray_t, AT_ELEMENT_ARRAY, "element_array" )
#endif // DMATTRIBUTETYPES_H

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

93
public/datamodel/dmvar.h Normal file
View File

@ -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

View File

@ -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