css_enhanced_waf/game/client/css_enhanced/variant_t.cpp

607 lines
15 KiB
C++
Raw Normal View History

#include "cbase.h"
#include "c_entityoutput.h"
#include "css_enhanced/variant_t.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// EVENTS save/restore parsing wrapper
CVariantSaveDataOps g_VariantSaveDataOps;
ISaveRestoreOps *variantFuncs = &g_VariantSaveDataOps;
CEventsSaveDataOps g_EventsSaveDataOps;
ISaveRestoreOps *eventFuncs = &g_EventsSaveDataOps;
#define classNameTypedef variant_t // to satisfy DEFINE... macros
typedescription_t variant_t::m_SaveBool[] =
{
DEFINE_FIELD( bVal, FIELD_BOOLEAN ),
};
typedescription_t variant_t::m_SaveInt[] =
{
DEFINE_FIELD( iVal, FIELD_INTEGER ),
};
typedescription_t variant_t::m_SaveFloat[] =
{
DEFINE_FIELD( flVal, FIELD_FLOAT ),
};
typedescription_t variant_t::m_SaveEHandle[] =
{
DEFINE_FIELD( eVal, FIELD_EHANDLE ),
};
typedescription_t variant_t::m_SaveString[] =
{
DEFINE_FIELD( iszVal, FIELD_STRING ),
};
typedescription_t variant_t::m_SaveColor[] =
{
DEFINE_FIELD( rgbaVal, FIELD_COLOR32 ),
};
#undef classNameTypedef
//
// Struct for saving and restoring vector variants, since they are
// stored as float[3] and we want to take advantage of position vector
// fixup across level transitions.
//
#define classNameTypedef variant_savevector_t // to satisfy DEFINE... macros
// BUGBUG: Add support for function pointer save/restore to variants
// BUGBUG: Must pass datamap_t to read/write fields
void variant_t::Set( fieldtype_t ftype, void *data )
{
fieldType = ftype;
switch ( ftype )
{
case FIELD_BOOLEAN: bVal = *((bool *)data); break;
case FIELD_CHARACTER: iVal = *((char *)data); break;
case FIELD_SHORT: iVal = *((short *)data); break;
case FIELD_INTEGER: iVal = *((int *)data); break;
case FIELD_STRING: iszVal = *((string_t *)data); break;
case FIELD_FLOAT: flVal = *((float *)data); break;
case FIELD_COLOR32: rgbaVal = *((color32 *)data); break;
case FIELD_VECTOR:
case FIELD_POSITION_VECTOR:
{
vecVal[0] = ((float *)data)[0];
vecVal[1] = ((float *)data)[1];
vecVal[2] = ((float *)data)[2];
break;
}
case FIELD_EHANDLE: eVal = *((EHANDLE *)data); break;
case FIELD_CLASSPTR: eVal = *((CBaseEntity **)data); break;
case FIELD_VOID:
default:
iVal = 0; fieldType = FIELD_VOID;
break;
}
}
//-----------------------------------------------------------------------------
// Purpose: Copies the value in the variant into a block of memory
// Input : *data - the block to write into
//-----------------------------------------------------------------------------
void variant_t::SetOther( void *data )
{
switch ( fieldType )
{
case FIELD_BOOLEAN: *((bool *)data) = bVal != 0; break;
case FIELD_CHARACTER: *((char *)data) = iVal; break;
case FIELD_SHORT: *((short *)data) = iVal; break;
case FIELD_INTEGER: *((int *)data) = iVal; break;
case FIELD_STRING: *((string_t *)data) = iszVal; break;
case FIELD_FLOAT: *((float *)data) = flVal; break;
case FIELD_COLOR32: *((color32 *)data) = rgbaVal; break;
case FIELD_VECTOR:
case FIELD_POSITION_VECTOR:
{
((float *)data)[0] = vecVal[0];
((float *)data)[1] = vecVal[1];
((float *)data)[2] = vecVal[2];
break;
}
case FIELD_EHANDLE: *((EHANDLE *)data) = eVal; break;
case FIELD_CLASSPTR: *((CBaseEntity **)data) = eVal; break;
}
}
//-----------------------------------------------------------------------------
// Purpose: Converts the variant to a new type. This function defines which I/O
// types can be automatically converted between. Connections that require
// an unsupported conversion will cause an error message at runtime.
// Input : newType - the type to convert to
// Output : Returns true on success, false if the conversion is not legal
//-----------------------------------------------------------------------------
bool variant_t::Convert( fieldtype_t newType )
{
if ( newType == fieldType )
{
return true;
}
//
// Converting to a null value is easy.
//
if ( newType == FIELD_VOID )
{
Set( FIELD_VOID, NULL );
return true;
}
//
// FIELD_INPUT accepts the variant type directly.
//
if ( newType == FIELD_INPUT )
{
return true;
}
switch ( fieldType )
{
case FIELD_INTEGER:
{
switch ( newType )
{
case FIELD_FLOAT:
{
SetFloat( (float) iVal );
return true;
}
case FIELD_BOOLEAN:
{
SetBool( iVal != 0 );
return true;
}
}
break;
}
case FIELD_FLOAT:
{
switch ( newType )
{
case FIELD_INTEGER:
{
SetInt( (int) flVal );
return true;
}
case FIELD_BOOLEAN:
{
SetBool( flVal != 0 );
return true;
}
}
break;
}
//
// Everyone must convert from FIELD_STRING if possible, since
// parameter overrides are always passed as strings.
//
case FIELD_STRING:
{
switch ( newType )
{
case FIELD_INTEGER:
{
if (iszVal != NULL_STRING)
{
SetInt(atoi(STRING(iszVal)));
}
else
{
SetInt(0);
}
return true;
}
case FIELD_FLOAT:
{
if (iszVal != NULL_STRING)
{
SetFloat(atof(STRING(iszVal)));
}
else
{
SetFloat(0);
}
return true;
}
case FIELD_BOOLEAN:
{
if (iszVal != NULL_STRING)
{
SetBool( atoi(STRING(iszVal)) != 0 );
}
else
{
SetBool(false);
}
return true;
}
case FIELD_VECTOR:
{
Vector tmpVec = vec3_origin;
if (sscanf(STRING(iszVal), "[%f %f %f]", &tmpVec[0], &tmpVec[1], &tmpVec[2]) == 0)
{
// Try sucking out 3 floats with no []s
sscanf(STRING(iszVal), "%f %f %f", &tmpVec[0], &tmpVec[1], &tmpVec[2]);
}
SetVector3D( tmpVec );
return true;
}
case FIELD_COLOR32:
{
int nRed = 0;
int nGreen = 0;
int nBlue = 0;
int nAlpha = 255;
sscanf(STRING(iszVal), "%d %d %d %d", &nRed, &nGreen, &nBlue, &nAlpha);
SetColor32( nRed, nGreen, nBlue, nAlpha );
return true;
}
case FIELD_EHANDLE:
{
// convert the string to an entity by locating it by classname
CBaseEntity *ent = NULL;
if ( iszVal != NULL_STRING )
{
// FIXME: do we need to pass an activator in here?
ent = UTIL_FindEntityByName( NULL, iszVal );
}
SetEntity( ent );
return true;
}
}
break;
}
case FIELD_EHANDLE:
{
switch ( newType )
{
case FIELD_STRING:
{
// take the entities targetname as the string
string_t iszStr = NULL_STRING;
if ( eVal != NULL )
{
SetString( MAKE_STRING(eVal->GetDebugName()) );
}
return true;
}
}
break;
}
}
// invalid conversion
return false;
}
//-----------------------------------------------------------------------------
// Purpose: All types must be able to display as strings for debugging purposes.
// Output : Returns a pointer to the string that represents this value.
//
// NOTE: The returned pointer should not be stored by the caller as
// subsequent calls to this function will overwrite the contents
// of the buffer!
//-----------------------------------------------------------------------------
const char *variant_t::ToString( void ) const
{
COMPILE_TIME_ASSERT( sizeof(string_t) == sizeof(intp) );
static char szBuf[512];
switch (fieldType)
{
case FIELD_STRING:
{
return(STRING(iszVal));
}
case FIELD_BOOLEAN:
{
if (bVal == 0)
{
Q_strncpy(szBuf, "false",sizeof(szBuf));
}
else
{
Q_strncpy(szBuf, "true",sizeof(szBuf));
}
return(szBuf);
}
case FIELD_INTEGER:
{
Q_snprintf( szBuf, sizeof( szBuf ), "%i", iVal );
return(szBuf);
}
case FIELD_FLOAT:
{
Q_snprintf(szBuf,sizeof(szBuf), "%g", flVal);
return(szBuf);
}
case FIELD_COLOR32:
{
Q_snprintf(szBuf,sizeof(szBuf), "%d %d %d %d", (int)rgbaVal.r, (int)rgbaVal.g, (int)rgbaVal.b, (int)rgbaVal.a);
return(szBuf);
}
case FIELD_VECTOR:
{
Q_snprintf(szBuf,sizeof(szBuf), "[%g %g %g]", (double)vecVal[0], (double)vecVal[1], (double)vecVal[2]);
return(szBuf);
}
case FIELD_VOID:
{
szBuf[0] = '\0';
return(szBuf);
}
case FIELD_EHANDLE:
{
const char *pszName = (Entity()) ? Entity()->GetDebugName() : "<<null entity>>";
Q_strncpy( szBuf, pszName, 512 );
return (szBuf);
}
}
return("No conversion to string");
}
struct variant_savevector_t
{
Vector vecSave;
};
typedescription_t variant_t::m_SaveVector[] =
{
// Just here to shut up ClassCheck
// DEFINE_ARRAY( vecVal, FIELD_FLOAT, 3 ),
DEFINE_FIELD( vecSave, FIELD_VECTOR ),
};
typedescription_t variant_t::m_SavePositionVector[] =
{
DEFINE_FIELD( vecSave, FIELD_POSITION_VECTOR ),
};
#undef classNameTypedef
#define classNameTypedef variant_savevmatrix_t // to satisfy DEFINE... macros
struct variant_savevmatrix_t
{
VMatrix matSave;
};
typedescription_t variant_t::m_SaveVMatrix[] =
{
DEFINE_FIELD( matSave, FIELD_VMATRIX ),
};
typedescription_t variant_t::m_SaveVMatrixWorldspace[] =
{
DEFINE_FIELD( matSave, FIELD_VMATRIX_WORLDSPACE ),
};
#undef classNameTypedef
#define classNameTypedef variant_savevmatrix3x4_t // to satisfy DEFINE... macros
struct variant_savevmatrix3x4_t
{
matrix3x4_t matSave;
};
typedescription_t variant_t::m_SaveMatrix3x4Worldspace[] =
{
DEFINE_FIELD( matSave, FIELD_MATRIX3X4_WORLDSPACE ),
};
#undef classNameTypedef
void CEventsSaveDataOps::Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave )
{
AssertMsg( fieldInfo.pTypeDesc->fieldSize == 1, "CEventsSaveDataOps does not support arrays");
C_BaseEntityOutput *ev = (C_BaseEntityOutput*)fieldInfo.pField;
const int fieldSize = fieldInfo.pTypeDesc->fieldSize;
for ( int i = 0; i < fieldSize; i++, ev++ )
{
// save out the number of fields
int numElements = ev->NumberOfElements();
pSave->WriteInt( &numElements, 1 );
// save the event data
ev->Save( *pSave );
}
}
void CEventsSaveDataOps::Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore )
{
AssertMsg( fieldInfo.pTypeDesc->fieldSize == 1, "CEventsSaveDataOps does not support arrays");
C_BaseEntityOutput *ev = (C_BaseEntityOutput*)fieldInfo.pField;
const int fieldSize = fieldInfo.pTypeDesc->fieldSize;
for ( int i = 0; i < fieldSize; i++, ev++ )
{
int nElements = pRestore->ReadInt();
Assert( nElements < 100 );
ev->Restore( *pRestore, nElements );
}
}
bool CEventsSaveDataOps::IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo )
{
AssertMsg( fieldInfo.pTypeDesc->fieldSize == 1, "CEventsSaveDataOps does not support arrays");
// check all the elements of the array (usually only 1)
C_BaseEntityOutput *ev = (C_BaseEntityOutput*)fieldInfo.pField;
const int fieldSize = fieldInfo.pTypeDesc->fieldSize;
for ( int i = 0; i < fieldSize; i++, ev++ )
{
// It's not empty if it has events or if it has a non-void variant value
if (( ev->NumberOfElements() != 0 ) || ( ev->ValueFieldType() != FIELD_VOID ))
return 0;
}
// variant has no data
return 1;
}
void CEventsSaveDataOps::MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo )
{
// Don't no how to. This is okay, since objects of this type
// are always born clean before restore, and not reused
}
bool CEventsSaveDataOps::Parse( const SaveRestoreFieldInfo_t &fieldInfo, char const* szValue )
{
C_BaseEntityOutput *ev = (C_BaseEntityOutput*)fieldInfo.pField;
ev->ParseEventAction( szValue );
return true;
}
// saves the entire array of variables
void CVariantSaveDataOps::Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave )
{
variant_t *var = (variant_t*)fieldInfo.pField;
int type = var->FieldType();
pSave->WriteInt( &type, 1 );
switch ( var->FieldType() )
{
case FIELD_VOID:
break;
case FIELD_BOOLEAN:
pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveBool, 1 );
break;
case FIELD_INTEGER:
pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveInt, 1 );
break;
case FIELD_FLOAT:
pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveFloat, 1 );
break;
case FIELD_EHANDLE:
pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveEHandle, 1 );
break;
case FIELD_STRING:
pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveString, 1 );
break;
case FIELD_COLOR32:
pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveColor, 1 );
break;
case FIELD_VECTOR:
{
variant_savevector_t Temp;
var->Vector3D(Temp.vecSave);
pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, &Temp, NULL, variant_t::m_SaveVector, 1 );
break;
}
case FIELD_POSITION_VECTOR:
{
variant_savevector_t Temp;
var->Vector3D(Temp.vecSave);
pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, &Temp, NULL, variant_t::m_SavePositionVector, 1 );
break;
}
default:
Warning( "Bad type %d in saved variant_t\n", var->FieldType() );
Assert(0);
}
}
// restores a single instance of the variable
void CVariantSaveDataOps::Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore )
{
variant_t *var = (variant_t*)fieldInfo.pField;
*var = variant_t();
var->fieldType = (_fieldtypes)pRestore->ReadInt();
switch ( var->fieldType )
{
case FIELD_VOID:
break;
case FIELD_BOOLEAN:
pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveBool, 1 );
break;
case FIELD_INTEGER:
pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveInt, 1 );
break;
case FIELD_FLOAT:
pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveFloat, 1 );
break;
case FIELD_EHANDLE:
pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveEHandle, 1 );
break;
case FIELD_STRING:
pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveString, 1 );
break;
case FIELD_COLOR32:
pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveColor, 1 );
break;
case FIELD_VECTOR:
{
variant_savevector_t Temp;
pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, &Temp, NULL, variant_t::m_SaveVector, 1 );
var->SetVector3D(Temp.vecSave);
break;
}
case FIELD_POSITION_VECTOR:
{
variant_savevector_t Temp;
pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, &Temp, NULL, variant_t::m_SavePositionVector, 1 );
var->SetPositionVector3D(Temp.vecSave);
break;
}
default:
Warning( "Bad type %d in saved variant_t\n", var->FieldType() );
Assert(0);
break;
}
}
bool CVariantSaveDataOps::IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo )
{
// check all the elements of the array (usually only 1)
variant_t *var = (variant_t*)fieldInfo.pField;
for ( int i = 0; i < fieldInfo.pTypeDesc->fieldSize; i++, var++ )
{
if ( var->FieldType() != FIELD_VOID )
return 0;
}
// variant has no data
return 1;
}
void CVariantSaveDataOps::MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo )
{
// Don't no how to. This is okay, since objects of this type
// are always born clean before restore, and not reused
}