You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
457 lines
20 KiB
457 lines
20 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#ifndef DATAMAP_H |
|
#define DATAMAP_H |
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
#ifndef VECTOR_H |
|
#include "mathlib/vector.h" |
|
#endif |
|
|
|
#include "tier1/utlvector.h" |
|
|
|
#include "tier0/memdbgon.h" |
|
|
|
// SINGLE_INHERITANCE restricts the size of CBaseEntity pointers-to-member-functions to 4 bytes |
|
class SINGLE_INHERITANCE CBaseEntity; |
|
struct inputdata_t; |
|
|
|
#define INVALID_TIME (FLT_MAX * -1.0) // Special value not rebased on save/load |
|
|
|
typedef enum _fieldtypes |
|
{ |
|
FIELD_VOID = 0, // No type or value |
|
FIELD_FLOAT, // Any floating point value |
|
FIELD_STRING, // A string ID (return from ALLOC_STRING) |
|
FIELD_VECTOR, // Any vector, QAngle, or AngularImpulse |
|
FIELD_QUATERNION, // A quaternion |
|
FIELD_INTEGER, // Any integer or enum |
|
FIELD_BOOLEAN, // boolean, implemented as an int, I may use this as a hint for compression |
|
FIELD_SHORT, // 2 byte integer |
|
FIELD_CHARACTER, // a byte |
|
FIELD_COLOR32, // 8-bit per channel r,g,b,a (32bit color) |
|
FIELD_EMBEDDED, // an embedded object with a datadesc, recursively traverse and embedded class/structure based on an additional typedescription |
|
FIELD_CUSTOM, // special type that contains function pointers to it's read/write/parse functions |
|
|
|
FIELD_CLASSPTR, // CBaseEntity * |
|
FIELD_EHANDLE, // Entity handle |
|
FIELD_EDICT, // edict_t * |
|
|
|
FIELD_POSITION_VECTOR, // A world coordinate (these are fixed up across level transitions automagically) |
|
FIELD_TIME, // a floating point time (these are fixed up automatically too!) |
|
FIELD_TICK, // an integer tick count( fixed up similarly to time) |
|
FIELD_MODELNAME, // Engine string that is a model name (needs precache) |
|
FIELD_SOUNDNAME, // Engine string that is a sound name (needs precache) |
|
|
|
FIELD_INPUT, // a list of inputed data fields (all derived from CMultiInputVar) |
|
FIELD_FUNCTION, // A class function pointer (Think, Use, etc) |
|
|
|
FIELD_VMATRIX, // a vmatrix (output coords are NOT worldspace) |
|
|
|
// NOTE: Use float arrays for local transformations that don't need to be fixed up. |
|
FIELD_VMATRIX_WORLDSPACE,// A VMatrix that maps some local space to world space (translation is fixed up on level transitions) |
|
FIELD_MATRIX3X4_WORLDSPACE, // matrix3x4_t that maps some local space to world space (translation is fixed up on level transitions) |
|
|
|
FIELD_INTERVAL, // a start and range floating point interval ( e.g., 3.2->3.6 == 3.2 and 0.4 ) |
|
FIELD_MODELINDEX, // a model index |
|
FIELD_MATERIALINDEX, // a material index (using the material precache string table) |
|
|
|
FIELD_VECTOR2D, // 2 floats |
|
|
|
FIELD_TYPECOUNT, // MUST BE LAST |
|
} fieldtype_t; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Field sizes... |
|
//----------------------------------------------------------------------------- |
|
template <int FIELD_TYPE> |
|
class CDatamapFieldSizeDeducer |
|
{ |
|
public: |
|
enum |
|
{ |
|
SIZE = 0 |
|
}; |
|
|
|
static int FieldSize( ) |
|
{ |
|
return 0; |
|
} |
|
}; |
|
|
|
#define DECLARE_FIELD_SIZE( _fieldType, _fieldSize ) \ |
|
template< > class CDatamapFieldSizeDeducer<_fieldType> { public: enum { SIZE = _fieldSize }; static int FieldSize() { return _fieldSize; } }; |
|
#define FIELD_SIZE( _fieldType ) CDatamapFieldSizeDeducer<_fieldType>::SIZE |
|
#define FIELD_BITS( _fieldType ) (FIELD_SIZE( _fieldType ) * 8) |
|
|
|
DECLARE_FIELD_SIZE( FIELD_FLOAT, sizeof(float) ) |
|
DECLARE_FIELD_SIZE( FIELD_STRING, sizeof(int) ) |
|
DECLARE_FIELD_SIZE( FIELD_VECTOR, 3 * sizeof(float) ) |
|
DECLARE_FIELD_SIZE( FIELD_VECTOR2D, 2 * sizeof(float) ) |
|
DECLARE_FIELD_SIZE( FIELD_QUATERNION, 4 * sizeof(float)) |
|
DECLARE_FIELD_SIZE( FIELD_INTEGER, sizeof(int)) |
|
DECLARE_FIELD_SIZE( FIELD_BOOLEAN, sizeof(char)) |
|
DECLARE_FIELD_SIZE( FIELD_SHORT, sizeof(short)) |
|
DECLARE_FIELD_SIZE( FIELD_CHARACTER, sizeof(char)) |
|
DECLARE_FIELD_SIZE( FIELD_COLOR32, sizeof(int)) |
|
DECLARE_FIELD_SIZE( FIELD_CLASSPTR, sizeof(int)) |
|
DECLARE_FIELD_SIZE( FIELD_EHANDLE, sizeof(int)) |
|
DECLARE_FIELD_SIZE( FIELD_EDICT, sizeof(int)) |
|
DECLARE_FIELD_SIZE( FIELD_POSITION_VECTOR, 3 * sizeof(float)) |
|
DECLARE_FIELD_SIZE( FIELD_TIME, sizeof(float)) |
|
DECLARE_FIELD_SIZE( FIELD_TICK, sizeof(int)) |
|
DECLARE_FIELD_SIZE( FIELD_MODELNAME, sizeof(int)) |
|
DECLARE_FIELD_SIZE( FIELD_SOUNDNAME, sizeof(int)) |
|
DECLARE_FIELD_SIZE( FIELD_INPUT, sizeof(int)) |
|
#ifdef POSIX |
|
// pointer to members under gnuc are 8bytes if you have a virtual func |
|
DECLARE_FIELD_SIZE( FIELD_FUNCTION, 2 * sizeof(void *)) |
|
#else |
|
DECLARE_FIELD_SIZE( FIELD_FUNCTION, sizeof(void *)) |
|
#endif |
|
DECLARE_FIELD_SIZE( FIELD_VMATRIX, 16 * sizeof(float)) |
|
DECLARE_FIELD_SIZE( FIELD_VMATRIX_WORLDSPACE, 16 * sizeof(float)) |
|
DECLARE_FIELD_SIZE( FIELD_MATRIX3X4_WORLDSPACE, 12 * sizeof(float)) |
|
DECLARE_FIELD_SIZE( FIELD_INTERVAL, 2 * sizeof( float) ) // NOTE: Must match interval.h definition |
|
DECLARE_FIELD_SIZE( FIELD_MODELINDEX, sizeof(int) ) |
|
DECLARE_FIELD_SIZE( FIELD_MATERIALINDEX, sizeof(int) ) |
|
|
|
|
|
#define ARRAYSIZE2D(p) (sizeof(p)/sizeof(p[0][0])) |
|
#define SIZE_OF_ARRAY(p) _ARRAYSIZE(p) |
|
|
|
#define _offsetof(s,m) ((int)&(((s *)0)->m)) |
|
|
|
#define _FIELD(name,fieldtype,count,flags,mapname,tolerance) { fieldtype, #name, { _offsetof(classNameTypedef, name), 0 }, count, flags, mapname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, tolerance } |
|
#define DEFINE_FIELD_NULL { FIELD_VOID,0, {0,0},0,0,0,0,0,0} |
|
#define DEFINE_FIELD(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_SAVE, NULL, 0 ) |
|
#define DEFINE_KEYFIELD(name,fieldtype, mapname) _FIELD(name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 ) |
|
#define DEFINE_KEYFIELD_NOT_SAVED(name,fieldtype, mapname)_FIELD(name, fieldtype, 1, FTYPEDESC_KEY, mapname, 0 ) |
|
#define DEFINE_AUTO_ARRAY(name,fieldtype) _FIELD(name, fieldtype, SIZE_OF_ARRAY(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, 0 ) |
|
#define DEFINE_AUTO_ARRAY_KEYFIELD(name,fieldtype,mapname) _FIELD(name, fieldtype, SIZE_OF_ARRAY(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, mapname, 0 ) |
|
#define DEFINE_ARRAY(name,fieldtype, count) _FIELD(name, fieldtype, count, FTYPEDESC_SAVE, NULL, 0 ) |
|
#define DEFINE_ENTITY_FIELD(name,fieldtype) _FIELD(edict_t, name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE, #name, 0 ) |
|
#define DEFINE_ENTITY_GLOBAL_FIELD(name,fieldtype) _FIELD(edict_t, name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE | FTYPEDESC_GLOBAL, #name, 0 ) |
|
#define DEFINE_GLOBAL_FIELD(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_GLOBAL | FTYPEDESC_SAVE, NULL, 0 ) |
|
#define DEFINE_GLOBAL_KEYFIELD(name,fieldtype, mapname) _FIELD(name, fieldtype, 1, FTYPEDESC_GLOBAL | FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 ) |
|
#define DEFINE_CUSTOM_FIELD(name,datafuncs) { FIELD_CUSTOM, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, datafuncs, NULL } |
|
#define DEFINE_CUSTOM_KEYFIELD(name,datafuncs,mapname) { FIELD_CUSTOM, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_KEY, mapname, datafuncs, NULL } |
|
#define DEFINE_AUTO_ARRAY2D(name,fieldtype) _FIELD(name, fieldtype, ARRAYSIZE2D(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, 0 ) |
|
// Used by byteswap datadescs |
|
#define DEFINE_BITFIELD(name,fieldtype,bitcount) DEFINE_ARRAY(name,fieldtype,((bitcount+FIELD_BITS(fieldtype)-1)&~(FIELD_BITS(fieldtype)-1)) / FIELD_BITS(fieldtype) ) |
|
#define DEFINE_INDEX(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_INDEX, NULL, 0 ) |
|
|
|
#define DEFINE_EMBEDDED( name ) \ |
|
{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name.m_DataMap), sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f } |
|
|
|
#define DEFINE_EMBEDDED_OVERRIDE( name, overridetype ) \ |
|
{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &((overridetype *)0)->m_DataMap, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f } |
|
|
|
#define DEFINE_EMBEDDEDBYREF( name ) \ |
|
{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( *(((classNameTypedef *)0)->name) ), NULL, 0, 0.0f } |
|
|
|
#define DEFINE_EMBEDDED_ARRAY( name, count ) \ |
|
{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, count, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f } |
|
|
|
#define DEFINE_EMBEDDED_AUTO_ARRAY( name ) \ |
|
{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, SIZE_OF_ARRAY( ((classNameTypedef *)0)->name ), FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f } |
|
|
|
#ifndef NO_ENTITY_PREDICTION |
|
|
|
#define DEFINE_PRED_TYPEDESCRIPTION( name, fieldtype ) \ |
|
{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &fieldtype::m_PredMap } |
|
|
|
#define DEFINE_PRED_TYPEDESCRIPTION_PTR( name, fieldtype ) \ |
|
{ FIELD_EMBEDDED, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &fieldtype::m_PredMap } |
|
|
|
#else |
|
|
|
#define DEFINE_PRED_TYPEDESCRIPTION( name, fieldtype ) DEFINE_FIELD_NULL |
|
#define DEFINE_PRED_TYPEDESCRIPTION_PTR( name, fieldtype ) DEFINE_FIELD_NULL |
|
|
|
#endif |
|
|
|
// Extensions to datamap.h macros for predicted entities only |
|
#define DEFINE_PRED_FIELD(name,fieldtype, flags) _FIELD(name, fieldtype, 1, flags, NULL, 0.0f ) |
|
#define DEFINE_PRED_ARRAY(name,fieldtype, count,flags) _FIELD(name, fieldtype, count, flags, NULL, 0.0f ) |
|
#define DEFINE_FIELD_NAME(localname,netname,fieldtype) _FIELD(localname, fieldtype, 1, 0, #netname, 0.0f ) |
|
// Predictable macros, which include a tolerance for floating point values... |
|
#define DEFINE_PRED_FIELD_TOL(name,fieldtype, flags,tolerance) _FIELD(name, fieldtype, 1, flags, NULL, tolerance ) |
|
#define DEFINE_PRED_ARRAY_TOL(name,fieldtype, count,flags,tolerance) _FIELD(name, fieldtype, count, flags, NULL, tolerance) |
|
#define DEFINE_FIELD_NAME_TOL(localname,netname,fieldtolerance) _FIELD(localname, fieldtype, 1, 0, #netname, tolerance ) |
|
|
|
//#define DEFINE_DATA( name, fieldextname, flags ) _FIELD(name, fieldtype, 1, flags, extname ) |
|
|
|
// INPUTS |
|
#define DEFINE_INPUT( name, fieldtype, inputname ) { fieldtype, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_INPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, inputname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ) } |
|
#define DEFINE_INPUTFUNC( fieldtype, inputname, inputfunc ) { fieldtype, #inputfunc, { NULL, NULL }, 1, FTYPEDESC_INPUT, inputname, NULL, static_cast <inputfunc_t> (&classNameTypedef::inputfunc) } |
|
|
|
// OUTPUTS |
|
// the variable 'name' MUST BE derived from CBaseOutput |
|
// we know the output type from the variable itself, so it doesn't need to be specified here |
|
class ISaveRestoreOps; |
|
extern ISaveRestoreOps *eventFuncs; |
|
#define DEFINE_OUTPUT( name, outputname ) { FIELD_CUSTOM, #name, { _offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_OUTPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, outputname, eventFuncs } |
|
|
|
// replaces EXPORT table for portability and non-DLL based systems (xbox) |
|
#define DEFINE_FUNCTION_RAW( function, func_type ) { FIELD_VOID, nameHolder.GenerateName(#function), { NULL, NULL }, 1, FTYPEDESC_FUNCTIONTABLE, NULL, NULL, (inputfunc_t)((func_type)(&classNameTypedef::function)) } |
|
#define DEFINE_FUNCTION( function ) DEFINE_FUNCTION_RAW( function, inputfunc_t ) |
|
|
|
|
|
#define FTYPEDESC_GLOBAL 0x0001 // This field is masked for global entity save/restore |
|
#define FTYPEDESC_SAVE 0x0002 // This field is saved to disk |
|
#define FTYPEDESC_KEY 0x0004 // This field can be requested and written to by string name at load time |
|
#define FTYPEDESC_INPUT 0x0008 // This field can be written to by string name at run time, and a function called |
|
#define FTYPEDESC_OUTPUT 0x0010 // This field propogates it's value to all targets whenever it changes |
|
#define FTYPEDESC_FUNCTIONTABLE 0x0020 // This is a table entry for a member function pointer |
|
#define FTYPEDESC_PTR 0x0040 // This field is a pointer, not an embedded object |
|
#define FTYPEDESC_OVERRIDE 0x0080 // The field is an override for one in a base class (only used by prediction system for now) |
|
|
|
// Flags used by other systems (e.g., prediction system) |
|
#define FTYPEDESC_INSENDTABLE 0x0100 // This field is present in a network SendTable |
|
#define FTYPEDESC_PRIVATE 0x0200 // The field is local to the client or server only (not referenced by prediction code and not replicated by networking) |
|
#define FTYPEDESC_NOERRORCHECK 0x0400 // The field is part of the prediction typedescription, but doesn't get compared when checking for errors |
|
|
|
#define FTYPEDESC_MODELINDEX 0x0800 // The field is a model index (used for debugging output) |
|
|
|
#define FTYPEDESC_INDEX 0x1000 // The field is an index into file data, used for byteswapping. |
|
|
|
// These flags apply to C_BasePlayer derived objects only |
|
#define FTYPEDESC_VIEW_OTHER_PLAYER 0x2000 // By default you can only view fields on the local player (yourself), |
|
// but if this is set, then we allow you to see fields on other players |
|
#define FTYPEDESC_VIEW_OWN_TEAM 0x4000 // Only show this data if the player is on the same team as the local player |
|
#define FTYPEDESC_VIEW_NEVER 0x8000 // Never show this field to anyone, even the local player (unusual) |
|
|
|
#define TD_MSECTOLERANCE 0.001f // This is a FIELD_FLOAT and should only be checked to be within 0.001 of the networked info |
|
|
|
struct typedescription_t; |
|
|
|
|
|
class ISaveRestoreOps; |
|
|
|
// |
|
// Function prototype for all input handlers. |
|
// |
|
typedef void (CBaseEntity::*inputfunc_t)(inputdata_t &data); |
|
|
|
struct datamap_t; |
|
struct typedescription_t; |
|
|
|
enum |
|
{ |
|
TD_OFFSET_NORMAL = 0, |
|
TD_OFFSET_PACKED = 1, |
|
|
|
// Must be last |
|
TD_OFFSET_COUNT, |
|
}; |
|
|
|
struct typedescription_t |
|
{ |
|
fieldtype_t fieldType; |
|
const char *fieldName; |
|
int fieldOffset[ TD_OFFSET_COUNT ]; // 0 == normal, 1 == packed offset |
|
unsigned short fieldSize; |
|
short flags; |
|
// the name of the variable in the map/fgd data, or the name of the action |
|
const char *externalName; |
|
// pointer to the function set for save/restoring of custom data types |
|
ISaveRestoreOps *pSaveRestoreOps; |
|
// for associating function with string names |
|
inputfunc_t inputFunc; |
|
// For embedding additional datatables inside this one |
|
datamap_t *td; |
|
|
|
// Stores the actual member variable size in bytes |
|
int fieldSizeInBytes; |
|
|
|
// FTYPEDESC_OVERRIDE point to first baseclass instance if chains_validated has occurred |
|
struct typedescription_t *override_field; |
|
|
|
// Used to track exclusion of baseclass fields |
|
int override_count; |
|
|
|
// Tolerance for field errors for float fields |
|
float fieldTolerance; |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: stores the list of objects in the hierarchy |
|
// used to iterate through an object's data descriptions |
|
//----------------------------------------------------------------------------- |
|
struct datamap_t |
|
{ |
|
typedescription_t *dataDesc; |
|
int dataNumFields; |
|
char const *dataClassName; |
|
datamap_t *baseMap; |
|
|
|
bool chains_validated; |
|
// Have the "packed" offsets been computed |
|
bool packed_offsets_computed; |
|
int packed_size; |
|
|
|
#if defined( _DEBUG ) |
|
bool bValidityChecked; |
|
#endif // _DEBUG |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// |
|
// Macros used to implement datadescs |
|
// |
|
#define DECLARE_SIMPLE_DATADESC() \ |
|
static datamap_t m_DataMap; \ |
|
static datamap_t *GetBaseMap(); \ |
|
template <typename T> friend void DataMapAccess(T *, datamap_t **p); \ |
|
template <typename T> friend datamap_t *DataMapInit(T *); |
|
|
|
#define DECLARE_DATADESC() \ |
|
DECLARE_SIMPLE_DATADESC() \ |
|
virtual datamap_t *GetDataDescMap( void ); |
|
|
|
#define BEGIN_DATADESC( className ) \ |
|
datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \ |
|
datamap_t *className::GetDataDescMap( void ) { return &m_DataMap; } \ |
|
datamap_t *className::GetBaseMap() { datamap_t *pResult; DataMapAccess((BaseClass *)NULL, &pResult); return pResult; } \ |
|
BEGIN_DATADESC_GUTS( className ) |
|
|
|
#define BEGIN_DATADESC_NO_BASE( className ) \ |
|
datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \ |
|
datamap_t *className::GetDataDescMap( void ) { return &m_DataMap; } \ |
|
datamap_t *className::GetBaseMap() { return NULL; } \ |
|
BEGIN_DATADESC_GUTS( className ) |
|
|
|
#define BEGIN_SIMPLE_DATADESC( className ) \ |
|
datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \ |
|
datamap_t *className::GetBaseMap() { return NULL; } \ |
|
BEGIN_DATADESC_GUTS( className ) |
|
|
|
#define BEGIN_SIMPLE_DATADESC_( className, BaseClass ) \ |
|
datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \ |
|
datamap_t *className::GetBaseMap() { datamap_t *pResult; DataMapAccess((BaseClass *)NULL, &pResult); return pResult; } \ |
|
BEGIN_DATADESC_GUTS( className ) |
|
|
|
#define BEGIN_DATADESC_GUTS( className ) \ |
|
template <typename T> datamap_t *DataMapInit(T *); \ |
|
template <> datamap_t *DataMapInit<className>( className * ); \ |
|
namespace className##_DataDescInit \ |
|
{ \ |
|
datamap_t *g_DataMapHolder = DataMapInit( (className *)NULL ); /* This can/will be used for some clean up duties later */ \ |
|
} \ |
|
\ |
|
template <> datamap_t *DataMapInit<className>( className * ) \ |
|
{ \ |
|
typedef className classNameTypedef; \ |
|
static CDatadescGeneratedNameHolder nameHolder(#className); \ |
|
className::m_DataMap.baseMap = className::GetBaseMap(); \ |
|
static typedescription_t dataDesc[] = \ |
|
{ \ |
|
{ FIELD_VOID,0, {0,0},0,0,0,0,0,0}, /* so you can define "empty" tables */ |
|
|
|
#define END_DATADESC() \ |
|
}; \ |
|
\ |
|
if ( sizeof( dataDesc ) > sizeof( dataDesc[0] ) ) \ |
|
{ \ |
|
classNameTypedef::m_DataMap.dataNumFields = SIZE_OF_ARRAY( dataDesc ) - 1; \ |
|
classNameTypedef::m_DataMap.dataDesc = &dataDesc[1]; \ |
|
} \ |
|
else \ |
|
{ \ |
|
classNameTypedef::m_DataMap.dataNumFields = 1; \ |
|
classNameTypedef::m_DataMap.dataDesc = dataDesc; \ |
|
} \ |
|
return &classNameTypedef::m_DataMap; \ |
|
} |
|
|
|
// used for when there is no data description |
|
#define IMPLEMENT_NULL_SIMPLE_DATADESC( derivedClass ) \ |
|
BEGIN_SIMPLE_DATADESC( derivedClass ) \ |
|
END_DATADESC() |
|
|
|
#define IMPLEMENT_NULL_SIMPLE_DATADESC_( derivedClass, baseClass ) \ |
|
BEGIN_SIMPLE_DATADESC_( derivedClass, baseClass ) \ |
|
END_DATADESC() |
|
|
|
#define IMPLEMENT_NULL_DATADESC( derivedClass ) \ |
|
BEGIN_DATADESC( derivedClass ) \ |
|
END_DATADESC() |
|
|
|
// helps get the offset of a bitfield |
|
#define BEGIN_BITFIELD( name ) \ |
|
union \ |
|
{ \ |
|
char name; \ |
|
struct \ |
|
{ |
|
|
|
#define END_BITFIELD() \ |
|
}; \ |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Forward compatability with potential seperate byteswap datadescs |
|
|
|
#define DECLARE_BYTESWAP_DATADESC() DECLARE_SIMPLE_DATADESC() |
|
#define BEGIN_BYTESWAP_DATADESC(name) BEGIN_SIMPLE_DATADESC(name) |
|
#define BEGIN_BYTESWAP_DATADESC_(name,base) BEGIN_SIMPLE_DATADESC_(name,base) |
|
#define END_BYTESWAP_DATADESC() END_DATADESC() |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
template <typename T> |
|
inline void DataMapAccess(T *ignored, datamap_t **p) |
|
{ |
|
*p = &T::m_DataMap; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
class CDatadescGeneratedNameHolder |
|
{ |
|
public: |
|
CDatadescGeneratedNameHolder( const char *pszBase ) |
|
: m_pszBase(pszBase) |
|
{ |
|
m_nLenBase = strlen( m_pszBase ); |
|
} |
|
|
|
~CDatadescGeneratedNameHolder() |
|
{ |
|
for ( int i = 0; i < m_Names.Count(); i++ ) |
|
{ |
|
delete m_Names[i]; |
|
} |
|
} |
|
|
|
const char *GenerateName( const char *pszIdentifier ) |
|
{ |
|
char *pBuf = new char[m_nLenBase + strlen(pszIdentifier) + 1]; |
|
strcpy( pBuf, m_pszBase ); |
|
strcat( pBuf, pszIdentifier ); |
|
m_Names.AddToTail( pBuf ); |
|
return pBuf; |
|
} |
|
|
|
private: |
|
const char *m_pszBase; |
|
size_t m_nLenBase; |
|
CUtlVector<char *> m_Names; |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
#include "tier0/memdbgoff.h" |
|
|
|
#endif // DATAMAP_H
|
|
|