aboutsummaryrefslogtreecommitdiff
path: root/sp/src/public/datamodel/dmelement.h
blob: 13a8becd1a18dbeda2834d6ed215bf8589e2d451 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
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