588 lines
25 KiB
C++
588 lines
25 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#ifndef DATAMAP_H
|
|
#define DATAMAP_H
|
|
#if _WIN32 && !defined(__GNUG__)
|
|
#pragma once
|
|
#endif
|
|
|
|
#ifndef VECTOR_H
|
|
#include "mathlib/vector.h"
|
|
#endif
|
|
|
|
#include "tier1/utlvector.h"
|
|
|
|
#include "tier0/memdbgon.h"
|
|
|
|
#if defined(_WIN32) && defined(__GNUG__)
|
|
//#include "../game/client/c_baseentity.h"
|
|
#endif
|
|
// 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, sizeof(uint64))
|
|
#else
|
|
DECLARE_FIELD_SIZE(FIELD_FUNCTION, sizeof(int *))
|
|
#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 _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
|