//========= Copyright © 1996-2005, Valve LLC, 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" //----------------------------------------------------------------------------- // Purpose: CDmeHandle is a templatized wrapper around DmElementHandle_t //----------------------------------------------------------------------------- template< class DmeType, HandleType_t HandleType = HT_WEAK > 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, HandleType > &handle ) : m_handle( DMELEMENT_HANDLE_INVALID ) { Set( handle.m_handle ); } template < class T, HandleType_t HT > CDmeHandle( const CDmeHandle< T, HT > &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, HandleType ); } template < class T, HandleType_t HT > CDmeHandle& operator=( const CDmeHandle< T, HT > &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, HandleType ); 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, HandleType ); } 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, HT_STRONG > CDmeCountedHandle; typedef CDmeHandle< CDmElement, HT_UNDO > CDmeUndoHandle; //----------------------------------------------------------------------------- // Vector of element handles //----------------------------------------------------------------------------- typedef CUtlVector< CDmeHandle > DmeHandleVec_t; // NOTE: these methods only append, so if there is already data in the list, it will remain template< typename T > inline void ConvertHandleToPtrVector( const CUtlVector< CDmeHandle< T > > &in, CUtlVector< T * > &out ) { int c = in.Count(); for ( int i = 0; i < c; ++i ) { out.AddToTail( in[ i ].Get() ); } } template< typename T > inline void ConvertPtrToHandleVector( const CUtlVector< T * > &in, CUtlVector< CDmeHandle< T > > &out ) { int c = in.Count(); for ( int i = 0; i < c; ++i ) { out.AddToTail( CDmeHandle< T >( in[ i ] ) ); } } //----------------------------------------------------------------------------- // 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 CDmeUndoHandle UndoStorageType; }; template<> class CDmAttributeUndoStorageType< CUtlVector< DmElementHandle_t > > { public: typedef CUtlVector< CDmeUndoHandle > UndoStorageType; }; #endif // DMEHANDLE_H