342 lines
9.4 KiB
C
342 lines
9.4 KiB
C
|
//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
|
||
|
//
|
||
|
// Included by networkvar.h
|
||
|
//
|
||
|
//==================================================================================================
|
||
|
|
||
|
#ifndef NETWORKVAR_VECTOR_H
|
||
|
#define NETWORKVAR_VECTOR_H
|
||
|
#ifdef _WIN32
|
||
|
#pragma once
|
||
|
#endif
|
||
|
|
||
|
|
||
|
// This is the normal case.. you've got a SendPropVector to match your CNetworkVector
|
||
|
#define CNetworkVector( name ) CNetworkVectorInternal( Vector, name, NetworkStateChanged, CNetworkVectorBase )
|
||
|
|
||
|
// This variant of a CNetworkVector should be used if you want to use SendPropFloat
|
||
|
// on each individual component of the vector.
|
||
|
#define CNetworkVectorXYZ( name ) CNetworkVectorInternal( Vector, name, NetworkStateChanged, CNetworkVectorXYZBase )
|
||
|
|
||
|
// This variant of a CNetworkVector should be used if you want to use SendPropVectorXY
|
||
|
// for the XY components and SendPropFloat for the Z component.
|
||
|
#define CNetworkVectorXY_SeparateZ( name ) CNetworkVectorInternal( Vector, name, NetworkStateChanged, CNetworkVectorXY_SeparateZBase )
|
||
|
|
||
|
|
||
|
|
||
|
// This is the normal case.. you've got a SendPropQAngle to match your CNetworkQAngle
|
||
|
#define CNetworkQAngle( name ) CNetworkVectorInternal( QAngle, name, NetworkStateChanged, CNetworkVectorBase )
|
||
|
|
||
|
// This variant of a CNetworkQAngle should be used if you want to use SendPropFloat
|
||
|
// on each individual component of the vector.
|
||
|
#define CNetworkQAngleXYZ( name ) CNetworkVectorInternal( QAngle, name, NetworkStateChanged, CNetworkVectorXYZBase )
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Use these variants if you want the networkvar to not trigger a change in the baseclass
|
||
|
// version but you might want it to trigger changes in derived classes that do network that variable.
|
||
|
//
|
||
|
#define CNetworkVectorForDerived( name ) \
|
||
|
virtual void NetworkStateChanged_##name() {} \
|
||
|
virtual void NetworkStateChanged_##name( void *pVar ) {} \
|
||
|
CNetworkVectorInternal( Vector, name, NetworkStateChanged_##name, CNetworkVectorBase )
|
||
|
|
||
|
#define CNetworkVectorXYZForDerived( name ) \
|
||
|
virtual void NetworkStateChanged_##name() {} \
|
||
|
virtual void NetworkStateChanged_##name( void *pVar ) {} \
|
||
|
CNetworkVectorInternal( Vector, name, NetworkStateChanged_##name, CNetworkVectorXYZBase )
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#define CNetworkVectorInternal( type, name, stateChangedFn, baseClass ) \
|
||
|
NETWORK_VAR_START( type, name ) \
|
||
|
NETWORK_VAR_END( type, name, baseClass, stateChangedFn )
|
||
|
|
||
|
|
||
|
|
||
|
// Network vector wrapper.
|
||
|
//
|
||
|
// The common base is shared between all CNetworkVectors.
|
||
|
// It includes everything but the Set() and operator=() functions,
|
||
|
// because the behavior of each of those is different for each vector type.
|
||
|
template< class Type, class Changer >
|
||
|
class CNetworkVectorCommonBase : public CNetworkVarBase< Type, Changer >
|
||
|
{
|
||
|
typedef CNetworkVarBase< Type, Changer > base;
|
||
|
public:
|
||
|
|
||
|
FORCEINLINE void Init( float ix=0, float iy=0, float iz=0 )
|
||
|
{
|
||
|
base::Set( Type( ix, iy, iz ) );
|
||
|
}
|
||
|
|
||
|
FORCEINLINE float GetX() const { return this->m_Value.x; }
|
||
|
FORCEINLINE float GetY() const { return this->m_Value.y; }
|
||
|
FORCEINLINE float GetZ() const { return this->m_Value.z; }
|
||
|
FORCEINLINE float operator[]( int i ) const { return this->m_Value[i]; }
|
||
|
|
||
|
FORCEINLINE bool operator==( const Type &val ) const
|
||
|
{
|
||
|
return this->m_Value == (Type)val;
|
||
|
}
|
||
|
|
||
|
FORCEINLINE bool operator!=( const Type &val ) const
|
||
|
{
|
||
|
return this->m_Value != (Type)val;
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type operator+( const Type &val ) const
|
||
|
{
|
||
|
return this->m_Value + val;
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type operator-( const Type &val ) const
|
||
|
{
|
||
|
return this->m_Value - val;
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type operator*( const Type &val ) const
|
||
|
{
|
||
|
return this->m_Value * val;
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& operator*=( float val )
|
||
|
{
|
||
|
return base::Set( this->m_Value * val );
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type operator*( float val ) const
|
||
|
{
|
||
|
return this->m_Value * val;
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type operator/( const Type &val ) const
|
||
|
{
|
||
|
return this->m_Value / val;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
FORCEINLINE void DetectChange( float &out, float in )
|
||
|
{
|
||
|
if ( out != in )
|
||
|
{
|
||
|
this->NetworkStateChanged();
|
||
|
out = in;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// This is for a CNetworkVector that only generates one change offset.
|
||
|
// It should only ever be used with SendPropVector/QAngle.
|
||
|
//
|
||
|
// Single-component things like SendPropFloat should never refer to it because
|
||
|
// they require the network var to report an offset for each component.
|
||
|
//
|
||
|
template< class Type, class Changer >
|
||
|
class CNetworkVectorBase : public CNetworkVectorCommonBase< Type, Changer >
|
||
|
{
|
||
|
typedef CNetworkVarBase< Type, Changer > base;
|
||
|
public:
|
||
|
static FORCEINLINE int GetNetworkVarFlags() { return NETWORKVAR_IS_A_VECTOR; }
|
||
|
|
||
|
FORCEINLINE const Type& operator=( const Type &val )
|
||
|
{
|
||
|
return base::Set( val );
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& operator=( const CNetworkVectorBase<Type,Changer> &val )
|
||
|
{
|
||
|
return base::Set( val.m_Value );
|
||
|
}
|
||
|
FORCEINLINE void SetX( float val ) { this->DetectChange( this->m_Value.x, val ); }
|
||
|
FORCEINLINE void SetY( float val ) { this->DetectChange( this->m_Value.y, val ); }
|
||
|
FORCEINLINE void SetZ( float val ) { this->DetectChange( this->m_Value.z, val ); }
|
||
|
FORCEINLINE void Set( int i, float val ) { this->DetectChange( this->m_Value[i], val ); }
|
||
|
|
||
|
FORCEINLINE const Type& operator*=( float val )
|
||
|
{
|
||
|
return base::Set( this->m_Value * val );
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
//
|
||
|
// This variant of a CNetworkVector should be used if you want to use SendPropFloat
|
||
|
// on each individual component of the vector.
|
||
|
//
|
||
|
template< class Type, class Changer >
|
||
|
class CNetworkVectorXYZBase : public CNetworkVectorCommonBase< Type, Changer >
|
||
|
{
|
||
|
typedef CNetworkVectorCommonBase< Type, Changer > base;
|
||
|
public:
|
||
|
|
||
|
static FORCEINLINE int GetNetworkVarFlags() { return NETWORKVAR_IS_A_VECTOR | NETWORKVAR_VECTOR_XYZ_FLAG; }
|
||
|
|
||
|
FORCEINLINE const Type& operator=( const Type &val )
|
||
|
{
|
||
|
return Set( val );
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& operator=( const CNetworkVectorBase<Type,Changer> &val )
|
||
|
{
|
||
|
return Set( val.m_Value );
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& Set( const Type &val )
|
||
|
{
|
||
|
SetX( val.x );
|
||
|
SetY( val.y );
|
||
|
SetZ( val.z );
|
||
|
|
||
|
return this->m_Value;
|
||
|
}
|
||
|
|
||
|
FORCEINLINE Type& GetForModify()
|
||
|
{
|
||
|
this->NetworkStateChanged( &((float*)this)[0] );
|
||
|
this->NetworkStateChanged( &((float*)this)[1] );
|
||
|
this->NetworkStateChanged( &((float*)this)[2] );
|
||
|
return this->m_Value;
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& SetDirect( const Type &val )
|
||
|
{
|
||
|
GetForModify() = val;
|
||
|
return this->m_Value;
|
||
|
}
|
||
|
|
||
|
FORCEINLINE void SetX( float val ) { DetectChange( 0, val ); }
|
||
|
FORCEINLINE void SetY( float val ) { DetectChange( 1, val ); }
|
||
|
FORCEINLINE void SetZ( float val ) { DetectChange( 2, val ); }
|
||
|
FORCEINLINE void Set( int i, float val ) { DetectChange( i, val ); }
|
||
|
|
||
|
FORCEINLINE const Type& operator+=( const Type &val )
|
||
|
{
|
||
|
return Set( this->m_Value + val );
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& operator-=( const Type &val )
|
||
|
{
|
||
|
return Set( this->m_Value - val );
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& operator*=( float val )
|
||
|
{
|
||
|
return Set( this->m_Value * val );
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& operator/=( float val )
|
||
|
{
|
||
|
return Set( this->m_Value / val );
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
FORCEINLINE void DetectChange( int nComponent, float in )
|
||
|
{
|
||
|
float *pVar = &((float*)this)[nComponent];
|
||
|
if ( *pVar != in )
|
||
|
{
|
||
|
if ( pVar != &((float*)this)[0] )
|
||
|
{
|
||
|
this->NetworkStateChanged( &((float*)this)[0] ); // Always mark the start of the vector as changed
|
||
|
}
|
||
|
this->NetworkStateChanged( pVar );
|
||
|
*pVar = in;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// This variant of a CNetworkVector should be used if you want to use SendPropVectorXY
|
||
|
// for the XY components and SendPropFloat for the Z component.
|
||
|
//
|
||
|
template< class Type, class Changer >
|
||
|
class CNetworkVectorXY_SeparateZBase : public CNetworkVectorCommonBase< Type, Changer >
|
||
|
{
|
||
|
typedef CNetworkVectorCommonBase< Type, Changer > base;
|
||
|
public:
|
||
|
|
||
|
static FORCEINLINE int GetNetworkVarFlags() { return NETWORKVAR_IS_A_VECTOR | NETWORKVAR_VECTOR_XY_SEPARATEZ_FLAG; }
|
||
|
|
||
|
FORCEINLINE const Type& operator=( const Type &val )
|
||
|
{
|
||
|
return Set( val );
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& operator=( const CNetworkVectorBase<Type,Changer> &val )
|
||
|
{
|
||
|
return Set( val.m_Value );
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& Set( const Type &val )
|
||
|
{
|
||
|
SetX( val.x );
|
||
|
SetY( val.y );
|
||
|
SetZ( val.z );
|
||
|
|
||
|
return this->m_Value;
|
||
|
}
|
||
|
|
||
|
FORCEINLINE Type& GetForModify()
|
||
|
{
|
||
|
this->NetworkStateChanged( &((float*)this)[0] ); // Mark the offset of our XY SendProp as changed.
|
||
|
this->NetworkStateChanged( &((float*)this)[2] ); // Mark the offset of our Z SendProp as changed.
|
||
|
return this->m_Value;
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& SetDirect( const Type &val )
|
||
|
{
|
||
|
GetForModify() = val;
|
||
|
return this->m_Value;
|
||
|
}
|
||
|
|
||
|
FORCEINLINE void SetX( float val ) { DetectChange( 0, val ); }
|
||
|
FORCEINLINE void SetY( float val ) { DetectChange( 1, val ); }
|
||
|
FORCEINLINE void SetZ( float val ) { DetectChange( 2, val ); }
|
||
|
FORCEINLINE void Set( int i, float val ) { DetectChange( i, val ); }
|
||
|
|
||
|
FORCEINLINE const Type& operator+=( const Type &val )
|
||
|
{
|
||
|
return Set( this->m_Value + val );
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& operator-=( const Type &val )
|
||
|
{
|
||
|
return Set( this->m_Value - val );
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& operator*=( float val )
|
||
|
{
|
||
|
return Set( this->m_Value * val );
|
||
|
}
|
||
|
|
||
|
FORCEINLINE const Type& operator/=( float val )
|
||
|
{
|
||
|
return Set( this->m_Value / val );
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
FORCEINLINE void DetectChange( int nComponent, float in )
|
||
|
{
|
||
|
float *pVar = &((float*)this)[nComponent];
|
||
|
if ( *pVar != in )
|
||
|
{
|
||
|
this->NetworkStateChanged( &((float*)this)[0] ); // Mark the offset of our XY SendProp as changed.
|
||
|
this->NetworkStateChanged( &((float*)this)[2] ); // Mark the offset of our Z SendProp as changed.
|
||
|
|
||
|
*pVar = in;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
#endif // NETWORKVAR_VECTOR_H
|
||
|
|