//===================== 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 &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 &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 &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