WIP: port alien swarm and extend engine for asw

This commit is contained in:
nillerusr
2023-10-03 20:02:58 +03:00
parent 7d3c0d8b5a
commit 8322130890
617 changed files with 161164 additions and 220 deletions
+1
View File
@@ -0,0 +1 @@
#include "IAppSystem.h"
+46
View File
@@ -0,0 +1,46 @@
//===== Copyright © 1996-2009, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef BITTOOLS_H
#define BITTOOLS_H
#ifdef _WIN32
#pragma once
#endif
namespace bittools
{
template<int N, int C = 0>
struct RecurseBit
{
enum {result = RecurseBit<N/2, C+1>::result};
};
template<int C>
struct RecurseBit<0, C>
{
enum {result = C};
};
template<int N, int C = 1>
struct RecursePow2
{
enum {result = RecursePow2<N/2, C*2>::result};
};
template<int C>
struct RecursePow2<0, C>
{
enum {result = C};
};
}
#define ROUND_TO_POWER_OF_2( n ) ( bittools::RecursePow2< (n) - 1 >::result )
#define MINIMUM_BITS_NEEDED( n ) ( bittools::RecurseBit< (n) - 1 >::result )
#endif //BITTOOLS_H
+48
View File
@@ -0,0 +1,48 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Macros for defining branching singletons.
//
// A branching singleton defines a singleton class within another class, and subclasses
// of the outer class can automatically expand on that singleton at their node in the
// class branching tree with the confidence that changes will be reflected in all
// subclasses.
//
// The primary reason to have a branching singleton is to centralize management code
// without being tied explicitly to one interface. The interface can possibly change
// vastly as it gets passed down the tree to the point where all the original functions
// are stubs and the interface uses an entirely different set of functions.
//
// $NoKeywords: $
//=============================================================================//
#ifndef BRANCHINGSINGLETON_H
#define BRANCHINGSINGLETON_H
#ifdef _WIN32
#pragma once
#endif
#define START_BRANCHING_SINGLETON_DEFINITION_NOBASE( classname ) class classname
#define START_BRANCHING_SINGLETON_DEFINITION( classname ) class classname : public Base##classname
#define _END_BRANCHING_SINGLETON_DEFINITION( classname );\
static classname *Get_##classname##_Static( void )\
{\
static classname s_Singleton;\
return &s_Singleton;\
}\
\
virtual Root##classname *Get_##classname##( void )\
{\
return Get_##classname##_Static();\
}\
typedef classname Base##classname;
#define END_BRANCHING_SINGLETON_DEFINITION( classname ) _END_BRANCHING_SINGLETON_DEFINITION( classname )
#define END_BRANCHING_SINGLETON_DEFINITION_NOBASE( classname );\
typedef classname Root##classname;\
_END_BRANCHING_SINGLETON_DEFINITION( classname );
#endif //#ifndef BRANCHINGSINGLETON_H
+4
View File
@@ -59,6 +59,7 @@ class IFileList;
class CRenamedRecvTableInfo;
class CMouthInfo;
class IConVar;
class ISPSharedMemory;
//-----------------------------------------------------------------------------
// Purpose: This data structure is filled in by the engine when the client .dll requests information about
@@ -519,6 +520,9 @@ public:
virtual uint OnStorageDeviceAttached( void ) = 0;
virtual void OnStorageDeviceDetached( void ) = 0;
//Finds or Creates a shared memory space, the returned pointer will automatically be AddRef()ed
virtual ISPSharedMemory *GetSinglePlayerSharedMemorySpace( const char *szName, int ent_num = MAX_EDICTS ) = 0;
virtual void ResetDemoInterpolation( void ) = 0;
// Methods to set/get a gamestats data container so client & server running in same process can send combined data
+62
View File
@@ -0,0 +1,62 @@
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "closedcaptions.h"
#include "filesystem.h"
#include "tier1/utlbuffer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// Assumed to be set up by calling code
bool AsyncCaption_t::LoadFromFile( char const *pchFullPath )
{
FileHandle_t fh = g_pFullFileSystem->Open( pchFullPath, "rb" );
if ( FILESYSTEM_INVALID_HANDLE == fh )
return false;
MEM_ALLOC_CREDIT();
CUtlBuffer dirbuffer;
// Read the header
g_pFullFileSystem->Read( &m_Header, sizeof( m_Header ), fh );
if ( m_Header.magic != COMPILED_CAPTION_FILEID )
{
if( IsPS3() )
return false;
else
Error( "Invalid file id for %s\n", pchFullPath );
}
if ( m_Header.version != COMPILED_CAPTION_VERSION )
{
if( IsPS3() )
return false;
else
Error( "Invalid file version for %s\n", pchFullPath );
}
if ( m_Header.directorysize < 0 || m_Header.directorysize > 64 * 1024 )
{
if( IsPS3() )
return false;
else
Error( "Invalid directory size %d for %s\n", m_Header.directorysize, pchFullPath );
}
//if ( m_Header.blocksize != MAX_BLOCK_SIZE )
// Error( "Invalid block size %d, expecting %d for %s\n", m_Header.blocksize, MAX_BLOCK_SIZE, pchFullPath );
int directoryBytes = m_Header.directorysize * sizeof( CaptionLookup_t );
m_CaptionDirectory.EnsureCapacity( m_Header.directorysize );
dirbuffer.EnsureCapacity( directoryBytes );
g_pFullFileSystem->Read( dirbuffer.Base(), directoryBytes, fh );
g_pFullFileSystem->Close( fh );
m_CaptionDirectory.CopyArray( (const CaptionLookup_t *)dirbuffer.PeekGet(), m_Header.directorysize );
m_CaptionDirectory.RedoSort( true );
m_DataBaseFile = pchFullPath;
return true;
}
+70
View File
@@ -0,0 +1,70 @@
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef CLOSEDCAPTIONS_H
#define CLOSEDCAPTIONS_H
#ifdef _WIN32
#pragma once
#endif
#include "captioncompiler.h"
#include "tier1/utlsymbol.h"
#include "tier1/utlsortvector.h"
FORWARD_DECLARE_HANDLE( memhandle_t );
typedef CUtlSortVector< CaptionLookup_t, CCaptionLookupLess > CaptionDictionary_t;
struct AsyncCaption_t
{
AsyncCaption_t() :
m_DataBaseFile( UTL_INVAL_SYMBOL ),
m_RequestedBlocks( 0, 0, BlockInfo_t::Less )
{
Q_memset( &m_Header, 0, sizeof( m_Header ) );
}
struct BlockInfo_t
{
int fileindex;
int blocknum;
memhandle_t handle;
static bool Less( const BlockInfo_t& lhs, const BlockInfo_t& rhs )
{
if ( lhs.fileindex != rhs.fileindex )
return lhs.fileindex < rhs.fileindex;
return lhs.blocknum < rhs.blocknum;
}
};
AsyncCaption_t& operator =( const AsyncCaption_t& rhs )
{
if ( this == &rhs )
return *this;
m_CaptionDirectory = rhs.m_CaptionDirectory;
m_Header = rhs.m_Header;
m_DataBaseFile = rhs.m_DataBaseFile;
for ( int i = rhs.m_RequestedBlocks.FirstInorder(); i != rhs.m_RequestedBlocks.InvalidIndex(); i = rhs.m_RequestedBlocks.NextInorder( i ) )
{
m_RequestedBlocks.Insert( rhs.m_RequestedBlocks[ i ] );
}
return *this;
}
bool LoadFromFile( char const *pchFullPath );
CUtlRBTree< BlockInfo_t, unsigned short > m_RequestedBlocks;
CaptionDictionary_t m_CaptionDirectory;
CompiledCaptionHeader_t m_Header;
CUtlSymbol m_DataBaseFile;
};
#endif // CLOSEDCAPTIONS_H
+8
View File
@@ -0,0 +1,8 @@
//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "Color.h"
+51
View File
@@ -0,0 +1,51 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
#ifndef IPRECACHESYSTEM_H
#define IPRECACHESYSTEM_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include "tier2/tier2.h"
#include "tier2/resourceprecacher.h"
#include "appframework/iappsystem.h"
//-----------------------------------------------------------------------------
// Resource access control API
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// IResourceAccessControl
// Purpose: Maintains lists of resources to use them as filters to prevent access
// to ensure proper precache behavior in game code
//-----------------------------------------------------------------------------
abstract_class IPrecacheSystem : public IAppSystem
{
public:
// Precaches/uncaches all resources used by a particular system
virtual void Cache( IPrecacheHandler *pPrecacheHandler, PrecacheSystem_t nSystem,
const char *pName, bool bPrecache, ResourceList_t hResourceList, bool bBuildResourceList ) = 0;
virtual void UncacheAll( IPrecacheHandler *pPrecacheHandler ) = 0 ;
virtual void Register( IResourcePrecacher *pResourcePrecacherFirst, PrecacheSystem_t nSystem ) = 0;
// Limits resource access to only resources used by this particular system
// Use GLOBAL system, and NULL name to disable limited resource access
virtual void LimitResourceAccess( PrecacheSystem_t nSystem, const char *pName ) = 0;
virtual void EndLimitedResourceAccess() = 0;
};
DECLARE_TIER2_INTERFACE( IPrecacheSystem, g_pPrecacheSystem );
#endif // IPRECACHESYSTEM_H
+11
View File
@@ -249,6 +249,17 @@ typedef void (CBaseEntity::*inputfunc_t)(inputdata_t &data);
struct datamap_t;
struct typedescription_t;
#if 0
enum
{
PC_NON_NETWORKED_ONLY = 0,
PC_NETWORKED_ONLY,
PC_COPYTYPE_COUNT,
PC_EVERYTHING = PC_COPYTYPE_COUNT,
};
#endif
enum
{
TD_OFFSET_NORMAL = 0,
+1
View File
@@ -61,6 +61,7 @@ public:
int maxEntities;
int serverCount;
edict_t *pEdicts;
};
inline CGlobalVars::CGlobalVars( bool bIsClient ) :
+5
View File
@@ -60,6 +60,7 @@ class CSteamID;
class IReplayFactory;
class IReplaySystem;
class IServer;
class ISPSharedMemory;
typedef struct player_info_s player_info_t;
@@ -402,6 +403,10 @@ public:
// Returns the SteamID of the specified player. It'll be NULL if the player hasn't authenticated yet.
virtual const CSteamID *GetClientSteamIDByPlayerIndex( int entnum ) = 0;
//Finds or Creates a shared memory space, the returned pointer will automatically be AddRef()ed
virtual ISPSharedMemory *GetSinglePlayerSharedMemorySpace( const char *szName, int ent_num = MAX_EDICTS ) = 0;
// Gets a list of all clusters' bounds. Returns total number of clusters.
virtual int GetClusterCount() = 0;
virtual int GetAllClusterBounds( bbox_t *pBBoxList, int maxBBox ) = 0;
+2
View File
@@ -32,8 +32,10 @@ public:
// These methods return the bounds of an OBB measured in "collision" space
// which can be retreived through the CollisionToWorldTransform or
// GetCollisionOrigin/GetCollisionAngles methods
#if !SOURCE_ASW
virtual const Vector& OBBMinsPreScaled() const = 0;
virtual const Vector& OBBMaxsPreScaled() const = 0;
#endif
virtual const Vector& OBBMins() const = 0;
virtual const Vector& OBBMaxs() const = 0;
+12 -4
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -75,24 +75,32 @@ public:
// Data access
virtual bool GetBool( const char *keyName = NULL, bool defaultValue = false ) = 0;
virtual int GetInt( const char *keyName = NULL, int defaultValue = 0 ) = 0;
virtual uint64 GetUint64( const char *keyName = NULL, uint64 defaultValue = 0 ) = 0;
virtual float GetFloat( const char *keyName = NULL, float defaultValue = 0.0f ) = 0;
virtual const char *GetString( const char *keyName = NULL, const char *defaultValue = "" ) = 0;
virtual void SetBool( const char *keyName, bool value ) = 0;
virtual void SetInt( const char *keyName, int value ) = 0;
virtual void SetUint64( const char *keyName, uint64 value ) = 0;
virtual void SetFloat( const char *keyName, float value ) = 0;
virtual void SetString( const char *keyName, const char *value ) = 0;
};
#define EVENT_DEBUG_ID_INIT 42
#define EVENT_DEBUG_ID_SHUTDOWN 13
abstract_class IGameEventListener2
{
public:
virtual ~IGameEventListener2( void ) {};
// FireEvent is called by EventManager if event just occurred
// FireEvent is called by EventManager if event just occured
// KeyValue memory will be freed by manager if not needed anymore
virtual void FireGameEvent( IGameEvent *event ) = 0;
#if SOURCE_ASW
virtual int GetEventDebugID( void ) = 0;
#endif
};
abstract_class IGameEventManager2 : public IBaseInterface
@@ -117,7 +125,7 @@ public:
// create an event by name, but doesn't fire it. returns NULL is event is not
// known or no listener is registered for it. bForce forces the creation even if no listener is active
virtual IGameEvent *CreateEvent( const char *name, bool bForce = false ) = 0;
virtual IGameEvent *CreateEvent( const char *name, bool bForce = false, int *pCookie = NULL ) = 0;
// fires a server event created earlier, if bDontBroadcast is set, event is not send to clients
virtual bool FireEvent( IGameEvent *event, bool bDontBroadcast = false ) = 0;
@@ -143,7 +151,7 @@ abstract_class IGameEventListener
public:
virtual ~IGameEventListener( void ) {};
// FireEvent is called by EventManager if event just occurred
// FireEvent is called by EventManager if event just occured
// KeyValue memory will be freed by manager if not needed anymore
virtual void FireGameEvent( KeyValues * event) = 0;
};
+27
View File
@@ -0,0 +1,27 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#ifndef ISPSHAREDMEMORY_H
#define ISPSHAREDMEMORY_H
#ifdef _WIN32
#pragma once
#endif
#include "basetypes.h"
#include "platform.h"
abstract_class ISPSharedMemory
{
public:
virtual bool Init( size_t iSize ) = 0; //Initial implementation assumes the size is fixed/hardcoded, returns true if this call actually created the memory, false if it already existed
virtual uint8 * Base( void ) = 0;
virtual size_t Size( void ) = 0;
virtual void AddRef( void ) = 0;
virtual void Release( void ) = 0;
};
#endif
+1 -1
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
+163 -123
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -21,9 +21,10 @@
#pragma warning( disable : 4284 ) // warning C4284: return type for 'CNetworkVarT<int>::operator ->' is 'int *' (ie; not a UDT or reference to a UDT. Will produce errors if applied using infix notation)
#define MyOffsetOf( type, var ) ( (intp)&((type*)0)->var )
#define MyOffsetOf( type, var ) ( (int)&((type*)0)->var )
#ifdef _DEBUG
#undef new
extern bool g_bUseNetworkVars;
#define CHECK_USENETWORKVARS if(g_bUseNetworkVars)
#else
@@ -32,6 +33,44 @@
// network vars use memcmp when fields are set. To ensure proper behavior your
// object's memory should be initialized to zero. This happens for entities automatically
// use this for other classes.
class CMemZeroOnNew
{
public:
void *operator new( size_t nSize )
{
void *pMem = MemAlloc_Alloc( nSize );
V_memset( pMem, 0, nSize );
return pMem;
}
void* operator new( size_t nSize, int nBlockUse, const char *pFileName, int nLine )
{
void *pMem = MemAlloc_Alloc( nSize, pFileName, nLine );
V_memset( pMem, 0, nSize );
return pMem;
}
void operator delete(void *pData)
{
if ( pData )
{
g_pMemAlloc->Free(pData);
}
}
void operator delete( void* pData, int nBlockUse, const char *pFileName, int nLine )
{
if ( pData )
{
g_pMemAlloc->Free(pData, pFileName, nLine );
}
}
};
inline int InternalCheckDeclareClass( const char *pClassName, const char *pClassNameMatch, void *pTestPtr, void *pBasePtr )
{
// This makes sure that casting from ThisClass to BaseClass works right. You'll get a compiler error if it doesn't
@@ -166,6 +205,7 @@ static inline void DispatchNetworkStateChanged( T *pObj, void *pVar )
template< class T > NetworkVar_##name& operator=( const T &val ) { *((type*)this) = val; return *this; } \
public: \
void CopyFrom( const type &src ) { *((type *)this) = src; NetworkStateChanged(); } \
type & GetForModify( void ) { NetworkStateChanged(); return *((type *)this); } \
virtual void NetworkStateChanged() \
{ \
DispatchNetworkStateChanged( (ThisClass_##name*)( ((char*)this) - GetOffset_##name() ) ); \
@@ -177,34 +217,32 @@ static inline void DispatchNetworkStateChanged( T *pObj, void *pVar )
}; \
NetworkVar_##name name;
template<typename T>
FORCEINLINE void NetworkVarConstruct( T &x ) { x = T(0); }
FORCEINLINE void NetworkVarConstruct( color32_s &x ) { x.r = x.g = x.b = x.a = 0; }
template< class Type, class Changer >
class CNetworkVarBase
{
public:
inline CNetworkVarBase()
CNetworkVarBase()
{
NetworkVarConstruct( m_Value );
}
template< class C >
const Type& operator=( const C &val )
{
return Set( ( const Type )val );
}
template< class C >
const Type& operator=( const CNetworkVarBase< C, Changer > &val )
{
return Set( ( const Type )val.m_Value );
}
const Type& Set( const Type &val )
FORCEINLINE explicit CNetworkVarBase( Type val )
: m_Value( val )
{
if ( memcmp( &m_Value, &val, sizeof(Type) ) )
NetworkStateChanged();
}
FORCEINLINE const Type& SetDirect( const Type &val )
{
NetworkStateChanged();
m_Value = val;
return m_Value;
}
FORCEINLINE const Type& Set( const Type &val )
{
if ( m_Value != val )
{
NetworkStateChanged();
m_Value = val;
@@ -212,66 +250,78 @@ public:
return m_Value;
}
Type& GetForModify()
template< class C >
FORCEINLINE const Type& operator=( const C &val )
{
return Set( ( const Type )val );
}
template< class C >
FORCEINLINE const Type& operator=( const CNetworkVarBase< C, Changer > &val )
{
return Set( ( const Type )val.m_Value );
}
FORCEINLINE Type& GetForModify()
{
NetworkStateChanged();
return m_Value;
}
template< class C >
const Type& operator+=( const C &val )
FORCEINLINE const Type& operator+=( const C &val )
{
return Set( m_Value + ( const Type )val );
}
template< class C >
const Type& operator-=( const C &val )
FORCEINLINE const Type& operator-=( const C &val )
{
return Set( m_Value - ( const Type )val );
}
template< class C >
const Type& operator/=( const C &val )
FORCEINLINE const Type& operator/=( const C &val )
{
return Set( m_Value / ( const Type )val );
}
template< class C >
const Type& operator*=( const C &val )
FORCEINLINE const Type& operator*=( const C &val )
{
return Set( m_Value * ( const Type )val );
}
template< class C >
const Type& operator^=( const C &val )
FORCEINLINE const Type& operator^=( const C &val )
{
return Set( m_Value ^ ( const Type )val );
}
template< class C >
const Type& operator|=( const C &val )
FORCEINLINE const Type& operator|=( const C &val )
{
return Set( m_Value | ( const Type )val );
}
const Type& operator++()
FORCEINLINE const Type& operator++()
{
return (*this += 1);
}
Type operator--()
FORCEINLINE Type operator--()
{
return (*this -= 1);
}
Type operator++( int ) // postfix version..
FORCEINLINE Type operator++( int ) // postfix version..
{
Type val = m_Value;
(*this += 1);
return val;
}
Type operator--( int ) // postfix version..
FORCEINLINE Type operator--( int ) // postfix version..
{
Type val = m_Value;
(*this -= 1);
@@ -282,22 +332,22 @@ public:
// CNetworkVarBase<unsigned char> = 0x1
// (it warns about converting from an int to an unsigned char).
template< class C >
const Type& operator&=( const C &val )
FORCEINLINE const Type& operator&=( const C &val )
{
return Set( m_Value & ( const Type )val );
}
operator const Type&() const
FORCEINLINE operator const Type&() const
{
return m_Value;
}
const Type& Get() const
FORCEINLINE const Type& Get() const
{
return m_Value;
}
const Type* operator->() const
FORCEINLINE const Type* operator->() const
{
return &m_Value;
}
@@ -305,16 +355,16 @@ public:
Type m_Value;
protected:
inline void NetworkStateChanged()
FORCEINLINE void NetworkStateChanged()
{
Changer::NetworkStateChanged( this );
}
};
template< class Type, class Changer >
class CNetworkColor32Base : public CNetworkVarBase< Type, Changer >
{
typedef CNetworkVarBase< Type, Changer > base;
public:
inline void Init( byte rVal, byte gVal, byte bVal )
{
@@ -332,29 +382,29 @@ public:
const Type& operator=( const Type &val )
{
return this->Set( val );
return Set( val );
}
const Type& operator=( const CNetworkColor32Base<Type,Changer> &val )
{
return CNetworkVarBase<Type,Changer>::Set( val.m_Value );
return base::Set( val.m_Value );
}
inline byte GetR() const { return CNetworkColor32Base<Type,Changer>::m_Value.r; }
inline byte GetG() const { return CNetworkColor32Base<Type,Changer>::m_Value.g; }
inline byte GetB() const { return CNetworkColor32Base<Type,Changer>::m_Value.b; }
inline byte GetA() const { return CNetworkColor32Base<Type,Changer>::m_Value.a; }
inline void SetR( byte val ) { SetVal( CNetworkColor32Base<Type,Changer>::m_Value.r, val ); }
inline void SetG( byte val ) { SetVal( CNetworkColor32Base<Type,Changer>::m_Value.g, val ); }
inline void SetB( byte val ) { SetVal( CNetworkColor32Base<Type,Changer>::m_Value.b, val ); }
inline void SetA( byte val ) { SetVal( CNetworkColor32Base<Type,Changer>::m_Value.a, val ); }
inline byte GetR() const { return this->m_Value.r; }
inline byte GetG() const { return this->m_Value.g; }
inline byte GetB() const { return this->m_Value.b; }
inline byte GetA() const { return this->m_Value.a; }
inline void SetR( byte val ) { SetVal( this->m_Value.r, val ); }
inline void SetG( byte val ) { SetVal( this->m_Value.g, val ); }
inline void SetB( byte val ) { SetVal( this->m_Value.b, val ); }
inline void SetA( byte val ) { SetVal( this->m_Value.a, val ); }
protected:
inline void SetVal( byte &out, const byte &in )
{
if ( out != in )
{
CNetworkVarBase< Type, Changer >::NetworkStateChanged();
this->NetworkStateChanged();
out = in;
}
}
@@ -365,80 +415,79 @@ protected:
template< class Type, class Changer >
class CNetworkVectorBase : public CNetworkVarBase< Type, Changer >
{
typedef CNetworkVarBase< Type, Changer > base;
public:
inline void Init( float ix=0, float iy=0, float iz=0 )
FORCEINLINE void Init( float ix=0, float iy=0, float iz=0 )
{
SetX( ix );
SetY( iy );
SetZ( iz );
base::Set( Type( ix, iy, iz ) );
}
const Type& operator=( const Type &val )
FORCEINLINE const Type& operator=( const Type &val )
{
return CNetworkVarBase< Type, Changer >::Set( val );
return base::Set( val );
}
const Type& operator=( const CNetworkVectorBase<Type,Changer> &val )
FORCEINLINE const Type& operator=( const CNetworkVectorBase<Type,Changer> &val )
{
return CNetworkVarBase<Type,Changer>::Set( val.m_Value );
return base::Set( val.m_Value );
}
inline float GetX() const { return CNetworkVectorBase<Type,Changer>::m_Value.x; }
inline float GetY() const { return CNetworkVectorBase<Type,Changer>::m_Value.y; }
inline float GetZ() const { return CNetworkVectorBase<Type,Changer>::m_Value.z; }
inline float operator[]( int i ) const { return CNetworkVectorBase<Type,Changer>::m_Value[i]; }
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]; }
inline void SetX( float val ) { DetectChange( CNetworkVectorBase<Type,Changer>::m_Value.x, val ); }
inline void SetY( float val ) { DetectChange( CNetworkVectorBase<Type,Changer>::m_Value.y, val ); }
inline void SetZ( float val ) { DetectChange( CNetworkVectorBase<Type,Changer>::m_Value.z, val ); }
inline void Set( int i, float val ) { DetectChange( CNetworkVectorBase<Type,Changer>::m_Value[i], val ); }
FORCEINLINE void SetX( float val ) { DetectChange( this->m_Value.x, val ); }
FORCEINLINE void SetY( float val ) { DetectChange( this->m_Value.y, val ); }
FORCEINLINE void SetZ( float val ) { DetectChange( this->m_Value.z, val ); }
FORCEINLINE void Set( int i, float val ) { DetectChange( this->m_Value[i], val ); }
bool operator==( const Type &val ) const
FORCEINLINE bool operator==( const Type &val ) const
{
return CNetworkVectorBase<Type,Changer>::m_Value == (Type)val;
return this->m_Value == (Type)val;
}
bool operator!=( const Type &val ) const
FORCEINLINE bool operator!=( const Type &val ) const
{
return CNetworkVectorBase<Type,Changer>::m_Value != (Type)val;
return this->m_Value != (Type)val;
}
const Type operator+( const Type &val ) const
FORCEINLINE const Type operator+( const Type &val ) const
{
return CNetworkVectorBase<Type,Changer>::m_Value + val;
return this->m_Value + val;
}
const Type operator-( const Type &val ) const
FORCEINLINE const Type operator-( const Type &val ) const
{
return CNetworkVectorBase<Type,Changer>::m_Value - val;
return this->m_Value - val;
}
const Type operator*( const Type &val ) const
FORCEINLINE const Type operator*( const Type &val ) const
{
return CNetworkVectorBase<Type,Changer>::m_Value * val;
return this->m_Value * val;
}
const Type& operator*=( float val )
FORCEINLINE const Type& operator*=( float val )
{
return CNetworkVarBase< Type, Changer >::Set( CNetworkVectorBase<Type,Changer>::m_Value * val );
return base::Set( this->m_Value * val );
}
const Type operator*( float val ) const
FORCEINLINE const Type operator*( float val ) const
{
return CNetworkVectorBase<Type,Changer>::m_Value * val;
return this->m_Value * val;
}
const Type operator/( const Type &val ) const
FORCEINLINE const Type operator/( const Type &val ) const
{
return CNetworkVectorBase<Type,Changer>::m_Value / val;
return this->m_Value / val;
}
private:
inline void DetectChange( float &out, float in )
FORCEINLINE void DetectChange( float &out, float in )
{
if ( out != in )
{
CNetworkVectorBase<Type,Changer>::NetworkStateChanged();
this->NetworkStateChanged();
out = in;
}
}
@@ -449,75 +498,73 @@ private:
template< class Type, class Changer >
class CNetworkQuaternionBase : public CNetworkVarBase< Type, Changer >
{
typedef CNetworkVarBase< Type, Changer > base;
public:
inline void Init( float ix=0, float iy=0, float iz=0, float iw = 0 )
{
SetX( ix );
SetY( iy );
SetZ( iz );
SetW( iw );
base::Set( Quaternion( ix, iy, iz, iw ) );
}
const Type& operator=( const Type &val )
{
return CNetworkVarBase< Type, Changer >::Set( val );
return Set( val );
}
const Type& operator=( const CNetworkQuaternionBase<Type,Changer> &val )
{
return CNetworkVarBase<Type,Changer>::Set( val.m_Value );
return Set( val.m_Value );
}
inline float GetX() const { return CNetworkQuaternionBase<Type,Changer>::m_Value.x; }
inline float GetY() const { return CNetworkQuaternionBase<Type,Changer>::m_Value.y; }
inline float GetZ() const { return CNetworkQuaternionBase<Type,Changer>::m_Value.z; }
inline float GetW() const { return CNetworkQuaternionBase<Type,Changer>::m_Value.w; }
inline float operator[]( int i ) const { return CNetworkQuaternionBase<Type,Changer>::m_Value[i]; }
inline float GetX() const { return this->m_Value.x; }
inline float GetY() const { return this->m_Value.y; }
inline float GetZ() const { return this->m_Value.z; }
inline float GetW() const { return this->m_Value.w; }
inline float operator[]( int i ) const { return this->m_Value[i]; }
inline void SetX( float val ) { DetectChange( CNetworkQuaternionBase<Type,Changer>::m_Value.x, val ); }
inline void SetY( float val ) { DetectChange( CNetworkQuaternionBase<Type,Changer>::m_Value.y, val ); }
inline void SetZ( float val ) { DetectChange( CNetworkQuaternionBase<Type,Changer>::m_Value.z, val ); }
inline void SetW( float val ) { DetectChange( CNetworkQuaternionBase<Type,Changer>::m_Value.w, val ); }
inline void Set( int i, float val ) { DetectChange( CNetworkQuaternionBase<Type,Changer>::m_Value[i], val ); }
inline void SetX( float val ) { DetectChange( this->m_Value.x, val ); }
inline void SetY( float val ) { DetectChange( this->m_Value.y, val ); }
inline void SetZ( float val ) { DetectChange( this->m_Value.z, val ); }
inline void SetW( float val ) { DetectChange( this->m_Value.w, val ); }
inline void Set( int i, float val ) { DetectChange( this->m_Value[i], val ); }
bool operator==( const Type &val ) const
{
return CNetworkQuaternionBase<Type,Changer>::m_Value == (Type)val;
return this->m_Value == (Type)val;
}
bool operator!=( const Type &val ) const
{
return CNetworkQuaternionBase<Type,Changer>::m_Value != (Type)val;
return this->m_Value != (Type)val;
}
const Type operator+( const Type &val ) const
{
return CNetworkQuaternionBase<Type,Changer>::m_Value + val;
return this->m_Value + val;
}
const Type operator-( const Type &val ) const
{
return CNetworkQuaternionBase<Type,Changer>::m_Value - val;
return this->m_Value - val;
}
const Type operator*( const Type &val ) const
{
return CNetworkQuaternionBase<Type,Changer>::m_Value * val;
return this->m_Value * val;
}
const Type& operator*=( float val )
{
return CNetworkQuaternionBase< Type, Changer >::Set( CNetworkQuaternionBase<Type,Changer>::m_Value * val );
return Set( this->m_Value * val );
}
const Type operator*( float val ) const
{
return CNetworkQuaternionBase<Type,Changer>::m_Value * val;
return this->m_Value * val;
}
const Type operator/( const Type &val ) const
{
return CNetworkQuaternionBase<Type,Changer>::m_Value / val;
return this->m_Value / val;
}
private:
@@ -525,7 +572,7 @@ private:
{
if ( out != in )
{
CNetworkQuaternionBase<Type,Changer>::NetworkStateChanged();
this->NetworkStateChanged();
out = in;
}
}
@@ -534,11 +581,10 @@ private:
// Network ehandle wrapper.
#if defined( CLIENT_DLL ) || defined( GAME_DLL )
inline void NetworkVarConstruct( CBaseHandle &x ) {}
template< class Type, class Changer >
class CNetworkHandleBase : public CNetworkVarBase< CBaseHandle, Changer >
{
typedef CNetworkVarBase< CBaseHandle, Changer > base;
public:
const Type* operator=( const Type *val )
{
@@ -553,12 +599,12 @@ private:
bool operator !() const
{
return !CNetworkHandleBase<Type,Changer>::m_Value.Get();
return !this->m_Value.Get();
}
operator Type*() const
{
return static_cast< Type* >( CNetworkHandleBase<Type,Changer>::m_Value.Get() );
return static_cast< Type* >( this->m_Value.Get() );
}
const Type* Set( const Type *val )
@@ -678,7 +724,6 @@ private:
class NetworkVar_##name \
{ \
public: \
NetworkVar_##name() { m_Value[0] = '\0'; } \
operator const char*() const { return m_Value; } \
const char* Get() const { return m_Value; } \
char* GetForModify() \
@@ -708,11 +753,6 @@ private:
class NetworkVar_##name \
{ \
public: \
inline NetworkVar_##name() \
{ \
for ( int i = 0 ; i < count ; ++i ) \
NetworkVarConstruct( m_Value[i] ); \
} \
template <typename T> friend int ServerClassInit(T *); \
const type& operator[]( int i ) const \
{ \
@@ -743,12 +783,12 @@ private:
} \
const type* Base() const { return m_Value; } \
int Count() const { return count; } \
protected: \
inline void NetworkStateChanged( int net_change_index ) \
{ \
CHECK_USENETWORKVARS ((ThisClass*)(((char*)this) - MyOffsetOf(ThisClass,name)))->stateChangedFn( &m_Value[net_change_index] ); \
} \
type m_Value[count]; \
protected: \
inline void NetworkStateChanged( int index ) \
{ \
CHECK_USENETWORKVARS ((ThisClass*)(((char*)this) - MyOffsetOf(ThisClass,name)))->stateChangedFn( &m_Value[index] ); \
} \
}; \
NetworkVar_##name name;
+341
View File
@@ -0,0 +1,341 @@
//===================== 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
+768
View File
@@ -0,0 +1,768 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
// Logging system declarations.
//
// The logging system is a channel-based output mechanism which allows
// subsystems to route their text/diagnostic output to various listeners
//
//===============================================================================
#ifndef LOGGING_H
#define LOGGING_H
#if !defined(__SPU__)
#if defined( COMPILER_MSVC )
#pragma once
#endif
#include "color.h"
#include "icommandline.h"
#include <stdio.h>
// For XBX_** functions
#if defined( _X360 )
#include "xbox/xbox_console.h"
#endif
// Used by CColorizedLoggingListener
#if defined( _WIN32 ) || (defined(POSIX) && !defined(_GAMECONSOLE))
#include "tier0/win32consoleio.h"
#endif
/*
---- Logging System ----
The logging system is a channel-based mechanism for all code (engine,
mod, tool) across all platforms to output information, warnings,
errors, etc.
This system supersedes the existing Msg(), Warning(), Error(), DevMsg(), ConMsg() etc. functions.
There are channels defined in the new system through which all old messages are routed;
see LOG_GENERAL, LOG_CONSOLE, LOG_DEVELOPER, etc.
To use the system, simply call one of the predefined macros:
Log_Msg( ChannelID, [Color], Message, ... )
Log_Warning( ChannelID, [Color], Message, ... )
Log_Error( ChannelID, [Color], Message, ... )
A ChannelID is typically created by defining a logging channel with the
log channel macros:
DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_ChannelName, "ChannelName", [Flags], [MinimumSeverity], [Color] );
or
BEGIN_DEFINE_LOGGING_CHANNEL( LOG_ChannelName, "ChannelName", [Flags], [MinimumSeverity], [Color] );
ADD_LOGGING_CHANNEL_TAG( "Tag1" );
ADD_LOGGING_CHANNEL_TAG( "Tag2" );
END_DEFINE_LOGGING_CHANNEL();
These macros create a global channel ID variable with the name specified
by the first parameter (in this example, LOG_ChannelName). This channel ID
can be used by various LoggingSystem_** functions to manipulate the channel settings.
The optional [Flags] parameter is an OR'd together set of LoggingChannelFlags_t
values (default: 0).
The optional [MinimumSeverity] parameter is the lowest threshold
above which messages will be processed (inclusive). The default is LS_MESSAGE,
which results in all messages, warnings, and errors being logged.
Variadic parameters to the Log_** functions will be ignored if a channel
is not enabled for a given severity (for performance reasons).
Logging channels can have their minimum severity modified by name, ID, or tag.
Logging channels are not hierarchical since there are situations in which
a channel needs to belong to multiple hierarchies. Use tags to create
categories or shallow hierarchies.
@TODO (Feature wishlist):
1) Callstack logging support
2) Registering dynamic channels and unregistering channels at runtime
3) Sentient robot to clean up the thousands of places using the old/legacy logging system.
*/
//////////////////////////////////////////////////////////////////////////
// Constants, Types, Forward Declares
//////////////////////////////////////////////////////////////////////////
class CLoggingSystem;
class CThreadFastMutex;
//-----------------------------------------------------------------------------
// Maximum length of a sprintf'ed logging message.
//-----------------------------------------------------------------------------
const int MAX_LOGGING_MESSAGE_LENGTH = 2048;
//-----------------------------------------------------------------------------
// Maximum length of a channel or tag name.
//-----------------------------------------------------------------------------
const int MAX_LOGGING_IDENTIFIER_LENGTH = 32;
//-----------------------------------------------------------------------------
// Maximum number of logging channels. Increase if needed.
//-----------------------------------------------------------------------------
const int MAX_LOGGING_CHANNEL_COUNT = 256;
//-----------------------------------------------------------------------------
// Maximum number of logging tags across all channels. Increase if needed.
//-----------------------------------------------------------------------------
const int MAX_LOGGING_TAG_COUNT = 1024;
//-----------------------------------------------------------------------------
// Maximum number of characters across all logging tags. Increase if needed.
//-----------------------------------------------------------------------------
const int MAX_LOGGING_TAG_CHARACTER_COUNT = 8192;
//-----------------------------------------------------------------------------
// Maximum number of concurrent logging listeners in a given logging state.
//-----------------------------------------------------------------------------
const int MAX_LOGGING_LISTENER_COUNT = 16;
//-----------------------------------------------------------------------------
// An invalid color set on a channel to imply that it should use
// a device-dependent default color where applicable.
//-----------------------------------------------------------------------------
const Color UNSPECIFIED_LOGGING_COLOR( 0, 0, 0, 0 );
//-----------------------------------------------------------------------------
// An ID returned by the logging system to refer to a logging channel.
//-----------------------------------------------------------------------------
typedef int LoggingChannelID_t;
//-----------------------------------------------------------------------------
// A sentinel value indicating an invalid logging channel ID.
//-----------------------------------------------------------------------------
const LoggingChannelID_t INVALID_LOGGING_CHANNEL_ID = -1;
//-----------------------------------------------------------------------------
// The severity of a logging operation.
//-----------------------------------------------------------------------------
enum LoggingSeverity_t
{
//-----------------------------------------------------------------------------
// An informative logging message.
//-----------------------------------------------------------------------------
LS_MESSAGE = 0,
//-----------------------------------------------------------------------------
// A warning, typically non-fatal
//-----------------------------------------------------------------------------
LS_WARNING = 1,
//-----------------------------------------------------------------------------
// A message caused by an Assert**() operation.
//-----------------------------------------------------------------------------
LS_ASSERT = 2,
//-----------------------------------------------------------------------------
// An error, typically fatal/unrecoverable.
//-----------------------------------------------------------------------------
LS_ERROR = 3,
//-----------------------------------------------------------------------------
// A placeholder level, higher than any legal value.
// Not a real severity value!
//-----------------------------------------------------------------------------
LS_HIGHEST_SEVERITY = 4,
};
//-----------------------------------------------------------------------------
// Action which should be taken by logging system as a result of
// a given logged message.
//
// The logging system invokes ILoggingResponsePolicy::OnLog() on
// the specified policy object, which returns a LoggingResponse_t.
//-----------------------------------------------------------------------------
enum LoggingResponse_t
{
LR_CONTINUE,
LR_DEBUGGER,
LR_ABORT,
};
//-----------------------------------------------------------------------------
// Logging channel behavior flags, set on channel creation.
//-----------------------------------------------------------------------------
enum LoggingChannelFlags_t
{
//-----------------------------------------------------------------------------
// Indicates that the spew is only relevant to interactive consoles.
//-----------------------------------------------------------------------------
LCF_CONSOLE_ONLY = 0x00000001,
//-----------------------------------------------------------------------------
// Indicates that spew should not be echoed to any output devices.
// A suitable logging listener must be registered which respects this flag
// (e.g. a file logger).
//-----------------------------------------------------------------------------
LCF_DO_NOT_ECHO = 0x00000002,
};
//-----------------------------------------------------------------------------
// A callback function used to register tags on a logging channel
// during initialization.
//-----------------------------------------------------------------------------
typedef void ( *RegisterTagsFunc )();
//-----------------------------------------------------------------------------
// A context structure passed to logging listeners and response policy classes.
//-----------------------------------------------------------------------------
struct LoggingContext_t
{
// ID of the channel being logged to.
LoggingChannelID_t m_ChannelID;
// Flags associated with the channel.
LoggingChannelFlags_t m_Flags;
// Severity of the logging event.
LoggingSeverity_t m_Severity;
// Color of logging message if one was specified to Log_****() macro.
// If not specified, falls back to channel color.
// If channel color is not specified, this value is UNSPECIFIED_LOGGING_COLOR
// and indicates that a suitable default should be chosen.
Color m_Color;
};
//-----------------------------------------------------------------------------
// Interface for classes to handle logging output.
//
// The Log() function of this class is called synchronously and serially
// by the logging system on all registered instances of ILoggingListener
// in the current "logging state".
//
// Derived classes may do whatever they want with the message (write to disk,
// write to console, send over the network, drop on the floor, etc.).
//
// In general, derived classes should do one, simple thing with the output
// to allow callers to register multiple, orthogonal logging listener classes.
//-----------------------------------------------------------------------------
class ILoggingListener
{
public:
virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage ) = 0;
};
//-----------------------------------------------------------------------------
// Interface for policy classes which determine how to behave when a
// message is logged.
//
// Can return:
// LR_CONTINUE (continue execution)
// LR_DEBUGGER (break into debugger if one is present, otherwise continue)
// LR_ABORT (terminate process immediately with a failure code of 1)
//-----------------------------------------------------------------------------
class ILoggingResponsePolicy
{
public:
virtual LoggingResponse_t OnLog( const LoggingContext_t *pContext ) = 0;
};
//////////////////////////////////////////////////////////////////////////
// Common Logging Listeners & Logging Response Policies
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
// A basic logging listener which prints to stdout and the debug channel.
//-----------------------------------------------------------------------------
class CSimpleLoggingListener : public ILoggingListener
{
public:
CSimpleLoggingListener( bool bQuietPrintf = false, bool bQuietDebugger = false ) :
m_bQuietPrintf( bQuietPrintf ),
m_bQuietDebugger( bQuietDebugger )
{
}
virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
{
#ifdef _X360
if ( !m_bQuietDebugger && XBX_IsConsoleConnected() )
{
// send to console
XBX_DebugString( XMAKECOLOR( 0,0,0 ), pMessage );
}
else
#endif
{
#if !defined( _CERT ) && !defined( DBGFLAG_STRINGS_STRIP )
if ( !m_bQuietPrintf )
{
_tprintf( _T("%s"), pMessage );
}
#endif
#ifdef _WIN32
if ( !m_bQuietDebugger && Plat_IsInDebugSession() )
{
Plat_DebugString( pMessage );
}
#endif
}
}
// If set to true, does not print anything to stdout.
bool m_bQuietPrintf;
// If set to true, does not print anything to debugger.
bool m_bQuietDebugger;
};
//-----------------------------------------------------------------------------
// A basic logging listener for GUI applications
//-----------------------------------------------------------------------------
class CSimpleWindowsLoggingListener : public ILoggingListener
{
public:
virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
{
if ( Plat_IsInDebugSession() )
{
Plat_DebugString( pMessage );
}
if ( pContext->m_Severity == LS_ERROR )
{
if ( Plat_IsInDebugSession() )
DebuggerBreak();
Plat_MessageBox( "Error", pMessage );
}
}
};
//-----------------------------------------------------------------------------
// ** NOTE FOR INTEGRATION **
// This was copied over from source 2 rather than integrated because
// source 2 has more significantly refactored tier0 logging.
//
// A logging listener with Win32 console API color support which which prints
// to stdout and the debug channel.
//-----------------------------------------------------------------------------
#if !defined(_GAMECONSOLE)
class CColorizedLoggingListener : public CSimpleLoggingListener
{
public:
CColorizedLoggingListener( bool bQuietPrintf = false, bool bQuietDebugger = false ) : CSimpleLoggingListener( bQuietPrintf, bQuietDebugger )
{
InitWin32ConsoleColorContext( &m_ColorContext );
}
virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
{
if ( !m_bQuietPrintf )
{
int nPrevColor = -1;
if ( pContext->m_Color != UNSPECIFIED_LOGGING_COLOR )
{
nPrevColor = SetWin32ConsoleColor( &m_ColorContext,
pContext->m_Color.r(), pContext->m_Color.g(), pContext->m_Color.b(),
MAX( MAX( pContext->m_Color.r(), pContext->m_Color.g() ), pContext->m_Color.b() ) > 128 );
}
_tprintf( _T("%s"), pMessage );
if ( nPrevColor >= 0 )
{
RestoreWin32ConsoleColor( &m_ColorContext, nPrevColor );
}
}
#ifdef _WIN32
if ( !m_bQuietDebugger && Plat_IsInDebugSession() )
{
Plat_DebugString( pMessage );
}
#endif
}
Win32ConsoleColorContext_t m_ColorContext;
};
#endif // !_GAMECONSOLE
//-----------------------------------------------------------------------------
// Default logging response policy used when one is not specified.
//-----------------------------------------------------------------------------
class CDefaultLoggingResponsePolicy : public ILoggingResponsePolicy
{
public:
virtual LoggingResponse_t OnLog( const LoggingContext_t *pContext )
{
if ( pContext->m_Severity == LS_ASSERT && !CommandLine()->FindParm( "-noassert" ) )
{
return LR_DEBUGGER;
}
else if ( pContext->m_Severity == LS_ERROR )
{
return LR_ABORT;
}
else
{
return LR_CONTINUE;
}
}
};
//-----------------------------------------------------------------------------
// A logging response policy which never terminates the process, even on error.
//-----------------------------------------------------------------------------
class CNonFatalLoggingResponsePolicy : public ILoggingResponsePolicy
{
public:
virtual LoggingResponse_t OnLog( const LoggingContext_t *pContext )
{
if ( ( pContext->m_Severity == LS_ASSERT && !CommandLine()->FindParm( "-noassert" ) ) || pContext->m_Severity == LS_ERROR )
{
return LR_DEBUGGER;
}
else
{
return LR_CONTINUE;
}
}
};
//////////////////////////////////////////////////////////////////////////
// Central Logging System
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
// The central logging system.
//
// Multiple instances can exist, though all exported tier0 functionality
// specifically works with a single global instance
// (via GetGlobalLoggingSystem()).
//-----------------------------------------------------------------------------
class CLoggingSystem
{
public:
struct LoggingChannel_t;
CLoggingSystem();
~CLoggingSystem();
//-----------------------------------------------------------------------------
// Register a logging channel with the logging system.
// The same channel can be registered multiple times, but the parameters
// in each call to RegisterLoggingChannel must either match across all calls
// or be set to defaults on any given call
//
// This function is not thread-safe and should generally only be called
// by a single thread. Using the logging channel definition macros ensures
// that this is called on the static initialization thread.
//-----------------------------------------------------------------------------
LoggingChannelID_t RegisterLoggingChannel( const char *pChannelName, RegisterTagsFunc registerTagsFunc, int flags = 0, LoggingSeverity_t minimumSeverity = LS_MESSAGE, Color spewColor = UNSPECIFIED_LOGGING_COLOR );
//-----------------------------------------------------------------------------
// Gets a channel ID from a string name.
// Performs a simple linear search; cache the value whenever possible
// or re-register the logging channel to get a global ID.
//-----------------------------------------------------------------------------
LoggingChannelID_t FindChannel( const char *pChannelName ) const;
int GetChannelCount() const { return m_nChannelCount; }
//-----------------------------------------------------------------------------
// Gets a pointer to the logging channel description.
//-----------------------------------------------------------------------------
LoggingChannel_t *GetChannel( LoggingChannelID_t channelID );
const LoggingChannel_t *GetChannel( LoggingChannelID_t channelID ) const;
//-----------------------------------------------------------------------------
// Returns true if the given channel has the specified tag.
//-----------------------------------------------------------------------------
bool HasTag( LoggingChannelID_t channelID, const char *pTag ) const { return GetChannel( channelID )->HasTag( pTag ); }
//-----------------------------------------------------------------------------
// Returns true if the given channel has been initialized.
// The main purpose is catching m_nChannelCount being zero because no channels have been registered.
//-----------------------------------------------------------------------------
bool IsValidChannelID( LoggingChannelID_t channelID ) const { return ( channelID >= 0 ) && ( channelID < m_nChannelCount ); }
//-----------------------------------------------------------------------------
// Returns true if the given channel will spew at the given severity level.
//-----------------------------------------------------------------------------
bool IsChannelEnabled( LoggingChannelID_t channelID, LoggingSeverity_t severity ) const { return IsValidChannelID( channelID ) && GetChannel( channelID )->IsEnabled( severity ); }
//-----------------------------------------------------------------------------
// Functions to set the spew level of a channel either directly by ID or
// string name, or for all channels with a given tag.
//
// These functions are not technically thread-safe but calling them across
// multiple threads should cause no significant problems
// (the underlying data types being changed are 32-bit/atomic).
//-----------------------------------------------------------------------------
void SetChannelSpewLevel( LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity );
void SetChannelSpewLevelByName( const char *pName, LoggingSeverity_t minimumSeverity );
void SetChannelSpewLevelByTag( const char *pTag, LoggingSeverity_t minimumSeverity );
void SetGlobalSpewLevel( LoggingSeverity_t minimumSeverity );
//-----------------------------------------------------------------------------
// Gets or sets the color of a logging channel.
// (The functions are not thread-safe, but the consequences are not
// significant.)
//-----------------------------------------------------------------------------
Color GetChannelColor( LoggingChannelID_t channelID ) const { return GetChannel( channelID )->m_SpewColor; }
void SetChannelColor( LoggingChannelID_t channelID, Color color ) { GetChannel( channelID )->m_SpewColor = color; }
//-----------------------------------------------------------------------------
// Gets or sets the flags on a logging channel.
// (The functions are not thread-safe, but the consequences are not
// significant.)
//-----------------------------------------------------------------------------
LoggingChannelFlags_t GetChannelFlags( LoggingChannelID_t channelID ) const { return GetChannel( channelID )->m_Flags; }
void SetChannelFlags( LoggingChannelID_t channelID, LoggingChannelFlags_t flags ) { GetChannel( channelID )->m_Flags = flags; }
//-----------------------------------------------------------------------------
// Adds a string tag to a channel.
// This is not thread-safe and should only be called by a RegisterTagsFunc
// callback passed in to RegisterLoggingChannel (via the
// channel definition macros).
//-----------------------------------------------------------------------------
void AddTagToCurrentChannel( const char *pTagName );
//-----------------------------------------------------------------------------
// Functions to save/restore the current logging state.
// Set bThreadLocal to true on a matching Push/Pop call if the intent
// is to override the logging listeners on the current thread only.
//
// Pushing the current logging state onto the state stack results
// in the current state being cleared by default (no listeners, default logging response policy).
// Set bClearState to false to copy the existing listener pointers to the new state.
//
// These functions which mutate logging state ARE thread-safe and are
// guarded by m_StateMutex.
//-----------------------------------------------------------------------------
void PushLoggingState( bool bThreadLocal = false, bool bClearState = true );
void PopLoggingState( bool bThreadLocal = false );
//-----------------------------------------------------------------------------
// Registers a logging listener (a class which handles logged messages).
//-----------------------------------------------------------------------------
void RegisterLoggingListener( ILoggingListener *pListener );
//-----------------------------------------------------------------------------
// Returns whether the specified logging listener is registered.
//-----------------------------------------------------------------------------
bool IsListenerRegistered( ILoggingListener *pListener );
//-----------------------------------------------------------------------------
// Clears out all of the current logging state (removes all listeners,
// sets the response policy to the default).
//-----------------------------------------------------------------------------
void ResetCurrentLoggingState();
//-----------------------------------------------------------------------------
// Sets a policy class to decide what should happen when messages of a
// particular severity are logged
// (e.g. exit on error, break into debugger).
// If pLoggingResponse is NULL, uses the default response policy class.
//-----------------------------------------------------------------------------
void SetLoggingResponsePolicy( ILoggingResponsePolicy *pLoggingResponse );
//-----------------------------------------------------------------------------
// Logs a message to the specified channel using a given severity and
// spew color. Passing in UNSPECIFIED_LOGGING_COLOR for 'color' allows
// the logging listeners to provide a default.
// NOTE: test 'IsChannelEnabled(channelID,severity)' before calling this!
//-----------------------------------------------------------------------------
LoggingResponse_t LogDirect( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color color, const tchar *pMessage );
// Internal data to represent a logging tag
struct LoggingTag_t
{
const char *m_pTagName;
LoggingTag_t *m_pNextTag;
};
// Internal data to represent a logging channel.
struct LoggingChannel_t
{
bool HasTag( const char *pTag ) const
{
LoggingTag_t *pCurrentTag = m_pFirstTag;
while( pCurrentTag != NULL )
{
if ( stricmp( pCurrentTag->m_pTagName, pTag ) == 0 )
{
return true;
}
pCurrentTag = pCurrentTag->m_pNextTag;
}
return false;
}
bool IsEnabled( LoggingSeverity_t severity ) const { return severity >= m_MinimumSeverity; }
void SetSpewLevel( LoggingSeverity_t severity ) { m_MinimumSeverity = severity; }
LoggingChannelID_t m_ID;
LoggingChannelFlags_t m_Flags; // an OR'd combination of LoggingChannelFlags_t
LoggingSeverity_t m_MinimumSeverity; // The minimum severity level required to activate this channel.
Color m_SpewColor;
char m_Name[MAX_LOGGING_IDENTIFIER_LENGTH];
LoggingTag_t *m_pFirstTag;
};
private:
// Represents the current state of the logger (registered listeners, response policy class, etc.) and can
// vary from thread-to-thread. It can also be pushed/popped to save/restore listener/response state.
struct LoggingState_t
{
// Index of the previous entry on the listener set stack.
int m_nPreviousStackEntry;
// Number of active listeners in this set. Cannot exceed MAX_LOGGING_LISTENER_COUNT.
// If set to -1, implies that this state structure is not in use.
int m_nListenerCount;
// Array of registered logging listener objects.
ILoggingListener *m_RegisteredListeners[MAX_LOGGING_LISTENER_COUNT];
// Specific policy class to determine behavior of logging system under specific message types.
ILoggingResponsePolicy *m_pLoggingResponse;
};
// These state functions to assume the caller has already grabbed the mutex.
LoggingState_t *GetCurrentState();
const LoggingState_t *GetCurrentState() const;
int FindUnusedStateIndex();
LoggingTag_t *AllocTag( const char *pTagName );
int m_nChannelCount;
LoggingChannel_t m_RegisteredChannels[MAX_LOGGING_CHANNEL_COUNT];
int m_nChannelTagCount;
LoggingTag_t m_ChannelTags[MAX_LOGGING_TAG_COUNT];
// Index to first free character in name pool.
int m_nTagNamePoolIndex;
// Pool of character data used for tag names.
char m_TagNamePool[MAX_LOGGING_TAG_CHARACTER_COUNT];
// Protects all data in this class except the registered channels
// (which are supposed to be registered using the macros at static/global init time).
// It is assumed that this mutex is reentrant safe on all platforms.
CThreadFastMutex *m_pStateMutex;
// The index of the current "global" state of the logging system. By default, all threads use this state
// for logging unless a given thread has pushed the logging state with bThreadLocal == true.
// If a thread-local state has been pushed, g_nThreadLocalStateIndex (a global thread-local integer) will be non-zero.
// By default, g_nThreadLocalStateIndex is 0 for all threads.
int m_nGlobalStateIndex;
// A pool of logging states used to store a stack (potentially per-thread).
static const int MAX_LOGGING_STATE_COUNT = 16;
LoggingState_t m_LoggingStates[MAX_LOGGING_STATE_COUNT];
// Default policy class which determines behavior.
CDefaultLoggingResponsePolicy m_DefaultLoggingResponse;
// Default spew function.
CSimpleLoggingListener m_DefaultLoggingListener;
};
//////////////////////////////////////////////////////////////////////////
// Logging Macros
//////////////////////////////////////////////////////////////////////////
// This macro will resolve to the most appropriate overload of LoggingSystem_Log() depending on the number of parameters passed in.
#ifdef DBGFLAG_STRINGS_STRIP
#define InternalMsg( Channel, Severity, /* [Color], Message, */ ... ) do { if ( Severity == LS_ERROR && LoggingSystem_IsChannelEnabled( Channel, Severity ) ) LoggingSystem_Log( Channel, Severity, /* [Color], Message, */ ##__VA_ARGS__ ); } while( 0 )
#else
#define InternalMsg( Channel, Severity, /* [Color], Message, */ ... ) do { if ( LoggingSystem_IsChannelEnabled( Channel, Severity ) ) LoggingSystem_Log( Channel, Severity, /* [Color], Message, */ ##__VA_ARGS__ ); } while( 0 )
#endif
//-----------------------------------------------------------------------------
// New macros, use these!
//
// The macros take an optional Color parameter followed by the message
// and the message formatting.
// We rely on the variadic macro (__VA_ARGS__) operator to paste in the
// extra parameters and resolve to the appropriate overload.
//-----------------------------------------------------------------------------
#define Log_Msg( Channel, /* [Color], Message, */ ... ) InternalMsg( Channel, LS_MESSAGE, /* [Color], Message, */ ##__VA_ARGS__ )
#define Log_Warning( Channel, /* [Color], Message, */ ... ) InternalMsg( Channel, LS_WARNING, /* [Color], Message, */ ##__VA_ARGS__ )
#define Log_Error( Channel, /* [Color], Message, */ ... ) InternalMsg( Channel, LS_ERROR, /* [Color], Message, */ ##__VA_ARGS__ )
#ifdef DBGFLAG_STRINGS_STRIP
#define Log_Assert( ... ) LR_CONTINUE
#else
#define Log_Assert( Message, ... ) LoggingSystem_LogAssert( Message, ##__VA_ARGS__ )
#endif
#define DECLARE_LOGGING_CHANNEL( Channel ) extern LoggingChannelID_t Channel
#define DEFINE_LOGGING_CHANNEL_NO_TAGS( Channel, ChannelName, /* [Flags], [Severity], [Color] */ ... ) \
LoggingChannelID_t Channel = LoggingSystem_RegisterLoggingChannel( ChannelName, NULL, ##__VA_ARGS__ )
#define BEGIN_DEFINE_LOGGING_CHANNEL( Channel, ChannelName, /* [Flags], [Severity], [Color] */ ... ) \
static void Register_##Channel##_Tags(); \
LoggingChannelID_t Channel = LoggingSystem_RegisterLoggingChannel( ChannelName, Register_##Channel##_Tags, ##__VA_ARGS__ ); \
void Register_##Channel##_Tags() \
{
#define ADD_LOGGING_CHANNEL_TAG( Tag ) LoggingSystem_AddTagToCurrentChannel( Tag )
#define END_DEFINE_LOGGING_CHANNEL() \
}
//////////////////////////////////////////////////////////////////////////
// DLL Exports
//////////////////////////////////////////////////////////////////////////
// For documentation on these functions, please look at the corresponding function
// in CLoggingSystem (unless otherwise specified).
PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_RegisterLoggingChannel( const char *pName, RegisterTagsFunc registerTagsFunc, int flags = 0, LoggingSeverity_t severity = LS_MESSAGE, Color color = UNSPECIFIED_LOGGING_COLOR );
PLATFORM_INTERFACE void LoggingSystem_RegisterLoggingListener( ILoggingListener *pListener );
PLATFORM_INTERFACE void LoggingSystem_UnregisterLoggingListener(ILoggingListener *pListener);
PLATFORM_INTERFACE void LoggingSystem_ResetCurrentLoggingState();
PLATFORM_INTERFACE void LoggingSystem_SetLoggingResponsePolicy( ILoggingResponsePolicy *pResponsePolicy );
// NOTE: PushLoggingState() saves the current logging state on a stack and results in a new clear state
// (no listeners, default logging response policy).
PLATFORM_INTERFACE void LoggingSystem_PushLoggingState( bool bThreadLocal = false, bool bClearState = true );
PLATFORM_INTERFACE void LoggingSystem_PopLoggingState( bool bThreadLocal = false );
PLATFORM_INTERFACE void LoggingSystem_AddTagToCurrentChannel( const char *pTagName );
// Returns INVALID_LOGGING_CHANNEL_ID if not found
PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_FindChannel( const char *pChannelName );
PLATFORM_INTERFACE int LoggingSystem_GetChannelCount();
PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_GetFirstChannelID();
// Returns INVALID_LOGGING_CHANNEL_ID when there are no channels remaining.
PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_GetNextChannelID( LoggingChannelID_t channelID );
PLATFORM_INTERFACE const CLoggingSystem::LoggingChannel_t *LoggingSystem_GetChannel( LoggingChannelID_t channelID );
PLATFORM_INTERFACE bool LoggingSystem_HasTag( LoggingChannelID_t channelID, const char *pTag );
PLATFORM_INTERFACE bool LoggingSystem_IsChannelEnabled( LoggingChannelID_t channelID, LoggingSeverity_t severity );
PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevel( LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity );
PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevelByName( const char *pName, LoggingSeverity_t minimumSeverity );
PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevelByTag( const char *pTag, LoggingSeverity_t minimumSeverity );
PLATFORM_INTERFACE void LoggingSystem_SetGlobalSpewLevel( LoggingSeverity_t minimumSeverity );
// Color is represented as an int32 due to C-linkage restrictions
PLATFORM_INTERFACE int32 LoggingSystem_GetChannelColor( LoggingChannelID_t channelID );
PLATFORM_INTERFACE void LoggingSystem_SetChannelColor( LoggingChannelID_t channelID, int color );
PLATFORM_INTERFACE LoggingChannelFlags_t LoggingSystem_GetChannelFlags( LoggingChannelID_t channelID );
PLATFORM_INTERFACE void LoggingSystem_SetChannelFlags( LoggingChannelID_t channelID, LoggingChannelFlags_t flags );
//-----------------------------------------------------------------------------
// Logs a variable-argument to a given channel with the specified severity.
// NOTE: if adding overloads to this function, remember that the Log_***
// macros simply pass their variadic parameters through to LoggingSystem_Log().
// Therefore, you need to ensure that the parameters are in the same general
// order and that there are no ambiguities with the overload.
//-----------------------------------------------------------------------------
PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_Log( LoggingChannelID_t channelID, LoggingSeverity_t severity, PRINTF_FORMAT_STRING const char *pMessageFormat, ... ) FMTFUNCTION( 3, 4 );
PLATFORM_OVERLOAD LoggingResponse_t LoggingSystem_Log( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, PRINTF_FORMAT_STRING const char *pMessageFormat, ... ) FMTFUNCTION( 4, 5 );
PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_LogDirect( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, const char *pMessage );
PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_LogAssert( PRINTF_FORMAT_STRING const char *pMessageFormat, ... ) FMTFUNCTION( 1, 2 );
#endif //#if !defined(__SPU__)
#endif // LOGGING_H
+18
View File
@@ -472,6 +472,18 @@ typedef void * HINSTANCE;
#endif
#define DebuggerBreakIfDebugging() if ( !Plat_IsInDebugSession() ) ; else DebuggerBreak()
//-----------------------------------------------------------------------------
// Message Box
//-----------------------------------------------------------------------------
//#if defined( PLATFORM_WINDOWS_PC )
//PLATFORM_INTERFACE void Plat_MessageBox( const char *pTitle, const tchar *pMessage );
//#else
// TODO(nillerusr): add message box later
#define Plat_MessageBox( t, m ) ((void)0)
//#endif
#ifdef STAGING_ONLY
#define DebuggerBreakIfDebugging_StagingOnly() if ( !Plat_IsInDebugSession() ) ; else DebuggerBreak()
#else
@@ -626,6 +638,12 @@ typedef void * HINSTANCE;
#define NO_ASAN
#endif
#if defined( COMPILER_MSVC )
#define TEMPLATE_STATIC static
#else
#define TEMPLATE_STATIC
#endif
#if defined( _WIN32 )
// Used for dll exporting and importing
+32
View File
@@ -0,0 +1,32 @@
//======= Copyright © 1996-2006, Valve Corporation, All rights reserved. ======
//
// Purpose: Win32 Console API helpers
//
//=============================================================================
#ifndef WIN32_CONSOLE_IO_H
#define WIN32_CONSOLE_IO_H
#if defined( COMPILER_MSVC )
#pragma once
#endif
// Function to attach a console for I/O to a Win32 GUI application in a reasonably smart fashion.
PLATFORM_INTERFACE bool SetupWin32ConsoleIO();
// Win32 Console Color API Helpers, originally from cmdlib.
struct Win32ConsoleColorContext_t
{
int m_InitialColor;
uint16 m_LastColor;
uint16 m_BadColor;
uint16 m_BackgroundFlags;
};
PLATFORM_INTERFACE void InitWin32ConsoleColorContext( Win32ConsoleColorContext_t *pContext );
PLATFORM_INTERFACE uint16 SetWin32ConsoleColor( Win32ConsoleColorContext_t *pContext, int nRed, int nGreen, int nBlue, int nIntensity );
PLATFORM_INTERFACE void RestoreWin32ConsoleColor( Win32ConsoleColorContext_t *pContext, uint16 prevColor );
#endif
+195
View File
@@ -0,0 +1,195 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Utilities for setting vproject settings
//
//===========================================================================//
#ifndef _RESOURCEPRECACHER_H
#define _RESOURCEPRECACHER_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Resource list
//-----------------------------------------------------------------------------
FORWARD_DECLARE_HANDLE( ResourceList_t );
#define RESOURCE_LIST_INVALID ( (ResourceList_t)-1 )
//-----------------------------------------------------------------------------
// Resource 'systems', which use other resources
// NOTE: If you add types here, be sure to fix s_pResourceSystemName
//-----------------------------------------------------------------------------
enum PrecacheSystem_t
{
CLIENTGLOBAL = 0, // Always precache these
SERVERGLOBAL,
VGUI_PANEL, // What to precache when using a vgui panel
DISPATCH_EFFECT, // What to precache when using a dispatch effect
SHARED_SYSTEM, // Precache lists which are reused and can be referenced as a resource type
PRECACHE_SYSTEM_COUNT,
#if defined( GAME_DLL )
GLOBAL = SERVERGLOBAL,
#elif defined( CLIENT_DLL ) || defined( GAMEUI_EXPORTS )
GLOBAL = CLIENTGLOBAL,
#endif
};
//-----------------------------------------------------------------------------
// Resource types
// NOTE: If you add a type here, modify s_pResourceTypeName in resourceaccesscontrol.cpp
//-----------------------------------------------------------------------------
enum ResourceTypeOld_t // called 'Old' to disambiguate with ResourceSystem
{
RESOURCE_VGUI_PANEL = 0, // .res file
RESOURCE_MATERIAL, // .vmt file
RESOURCE_MODEL, // .mdl file
RESOURCE_PARTICLE_SYSTEM, // particle system
RESOURCE_GAMESOUND, // game sound
RESOURCE_TYPE_OLD_COUNT,
};
//-----------------------------------------------------------------------------
// Resource types
// NOTE: If you add types here, be sure to fix s_pPrecacheResourceTypeName
// A compile-time assert will trigger if you don't.
//-----------------------------------------------------------------------------
enum PrecacheResourceType_t
{
VGUI_RESOURCE = 0, // .res file
MATERIAL, // .vmt file
MODEL, // .mdl file
GAMESOUND, // sound
PARTICLE_SYSTEM, // particle system
ENTITY, // Other entity
DECAL, // A decal
PARTICLE_MATERIAL, // A particle system material (old-style, obsolete)
KV_DEP_FILE, // keyvalues file containing a resource dependency list
GAME_MATERIAL_DECALS, // All decals related to game materials ( resource name is ignored )
PHYSICS_GAMESOUNDS, // Resource names are either "BulletSounds", "StepSounds", or "PhysicsImpactSounds"
SHARED, // a shared precache group (see PrecacheSystem_t SHARED)
PRECACHE_RESOURCE_TYPE_COUNT,
};
//-----------------------------------------------------------------------------
// Callback interface for handler who knows how to precache particular kinds of resources
//-----------------------------------------------------------------------------
abstract_class IPrecacheHandler
{
public:
virtual void CacheResource( PrecacheResourceType_t nType, const char *pName,
bool bPrecache, ResourceList_t hResourceList, int *pIndex = NULL ) = 0;
};
//-----------------------------------------------------------------------------
// Interface to automated system for precaching resources
//-----------------------------------------------------------------------------
abstract_class IResourcePrecacher
{
public:
virtual void Cache( IPrecacheHandler *pPrecacheHandler, bool bPrecache, ResourceList_t hResourceList, bool bIgnoreConditionals ) = 0;
virtual PrecacheSystem_t GetSystem() = 0;
virtual const char *GetName() = 0;
virtual IResourcePrecacher *GetNext() = 0;
virtual void SetNext( IResourcePrecacher * pNext ) = 0;
};
//-----------------------------------------------------------------------------
// Actually does the precaching
//-----------------------------------------------------------------------------
class CBaseResourcePrecacher : public IResourcePrecacher
{
// Other public methods
public:
CBaseResourcePrecacher( PrecacheSystem_t nSystem, const char *pName )
{
m_nSystem = nSystem;
m_pName = pName;
m_pNext = sm_pFirst[nSystem];
sm_pFirst[nSystem] = this;
}
static void RegisterAll();
PrecacheSystem_t GetSystem() { return m_nSystem; }
const char *GetName() { return m_pName; }
IResourcePrecacher *GetNext() { return m_pNext; }
void SetNext( IResourcePrecacher * pNext ) { m_pNext = pNext; }
static CBaseResourcePrecacher *sm_pFirst[PRECACHE_SYSTEM_COUNT];
PrecacheSystem_t m_nSystem;
const char *m_pName;
IResourcePrecacher *m_pNext;
friend class CPrecacheRegister;
};
//-----------------------------------------------------------------------------
// Automatic precache macros
//-----------------------------------------------------------------------------
// Beginning
#define PRECACHE_REGISTER_BEGIN_CONDITIONAL( _system, _className, _condition ) \
namespace _className ## Precache \
{ \
class CResourcePrecacher : public CBaseResourcePrecacher\
{ \
public: \
CResourcePrecacher() : CBaseResourcePrecacher( _system, #_className ) {} \
public: \
virtual void Cache( IPrecacheHandler *pPrecacheHandler, bool bPrecache, ResourceList_t hResourceList, bool bIgnoreConditionals ); \
}; \
void CResourcePrecacher::Cache( IPrecacheHandler *pPrecacheHandler, bool bPrecache, ResourceList_t hResourceList, bool bIgnoreConditionals ) \
{ \
if ( !bIgnoreConditionals && !( _condition ) ) \
return;
#define PRECACHE_REGISTER_BEGIN( _system, _className ) \
PRECACHE_REGISTER_BEGIN_CONDITIONAL( _system, _className, true )
// Resource precache definitions
#define PRECACHE( _type, _name ) pPrecacheHandler->CacheResource( _type, _name, bPrecache, hResourceList, NULL );
// NOTE: PRECACHE_INDEX_CONDITIONAL doesn't initialize the index to 0
// on the assumption that some other conditional will
//MCCLEANUP //NOTE: PRECACHE_INDEX and PRECACHE_INDEX_CONDITIONAL won't work in 64 bit because the old-school particle mgr is sending ptr data types into here. Hopefully the old-school particle mgr will die before this is an issue.
#define PRECACHE_INDEX( _type, _name, _index ) pPrecacheHandler->CacheResource( _type, _name, bPrecache, hResourceList, (int*)( &(_index) ) );
#define PRECACHE_CONDITIONAL( _type, _name, _condition ) \
if ( !bIgnoreConditionals && ( _condition ) ) \
pPrecacheHandler->CacheResource( _type, _name, bPrecache, hResourceList, NULL );
#define PRECACHE_INDEX_CONDITIONAL( _type, _name, _index, _func ) \
if ( bIgnoreConditionals || ( _condition ) ) \
{ \
pPrecacheHandler->CacheResource( _type, _name, bPrecache, hResourceList, (int*)( &(_index) ) ); \
}
//End
#define PRECACHE_REGISTER_END( ) \
} \
CResourcePrecacher s_ResourcePrecacher; \
}
// FIXME: Remove! Backward compat
#define PRECACHE_WEAPON_REGISTER( _className ) \
PRECACHE_REGISTER_BEGIN( GLOBAL, _className ) \
PRECACHE( ENTITY, #_className ) \
PRECACHE_REGISTER_END()
#define PRECACHE_REGISTER( _className ) \
PRECACHE_REGISTER_BEGIN( GLOBAL, _className ) \
PRECACHE( ENTITY, #_className ) \
PRECACHE_REGISTER_END()
#endif // _RESOURCEPRECACHER_H
+72
View File
@@ -0,0 +1,72 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
// Tier2 logging helpers. Adds support for file I/O
//
//===============================================================================
#ifndef TIER2_LOGGING_H
#define TIER2_LOGGING_H
#if defined( COMPILER_MSVC )
#pragma once
#endif
#include "logging.h"
const int MAX_SIMULTANEOUS_LOGGING_FILE_COUNT = 16;
const int INVALID_LOGGING_FILE_HANDLE = -1;
typedef int LoggingFileHandle_t;
typedef void * FileHandle_t;
#define FILELOGGINGLISTENER_INTERFACE_VERSION "FileLoggingListener001"
abstract_class IFileLoggingListener : public ILoggingListener
{
public:
virtual void Log( const LoggingContext_t *pContext, const char *pMessage ) = 0;
virtual LoggingFileHandle_t BeginLoggingToFile( const char *pFilename, const char *pOptions, const char *pPathID = NULL ) = 0;
virtual void EndLoggingToFile( LoggingFileHandle_t fileHandle ) = 0;
virtual void AssignLogChannel( LoggingChannelID_t channelID, LoggingFileHandle_t loggingFileHandle ) = 0;
virtual void UnassignLogChannel( LoggingChannelID_t channelID ) = 0;
virtual void AssignAllLogChannels( LoggingFileHandle_t loggingFileHandle ) = 0;
virtual void UnassignAllLogChannels() = 0;
};
class CFileLoggingListener : public IFileLoggingListener
{
public:
CFileLoggingListener();
~CFileLoggingListener();
virtual void Log( const LoggingContext_t *pContext, const char *pMessage );
virtual LoggingFileHandle_t BeginLoggingToFile( const char *pFilename, const char *pOptions, const char *pPathID = NULL );
virtual void EndLoggingToFile( LoggingFileHandle_t fileHandle );
virtual void AssignLogChannel( LoggingChannelID_t channelID, LoggingFileHandle_t loggingFileHandle );
virtual void UnassignLogChannel( LoggingChannelID_t channelID );
virtual void AssignAllLogChannels( LoggingFileHandle_t loggingFileHandle );
virtual void UnassignAllLogChannels();
private:
int GetUnusedFileInfo() const;
struct FileInfo_t
{
FileHandle_t m_FileHandle;
bool IsOpen() const { return m_FileHandle != 0; }
void Reset() { m_FileHandle = 0; }
};
FileInfo_t m_OpenFiles[MAX_SIMULTANEOUS_LOGGING_FILE_COUNT];
// Table which maps logging channel IDs to open files
int m_FileIndices[MAX_LOGGING_CHANNEL_COUNT];
};
#endif // TIER2_LOGGING_H
File diff suppressed because it is too large Load Diff
+521
View File
@@ -0,0 +1,521 @@
//========== Copyright (c) 2008, Valve Corporation, All rights reserved. ========
//
// Purpose:
//
//=============================================================================
#ifndef VSCRIPT_TEMPLATES_H
#define VSCRIPT_TEMPLATES_H
#include "tier0/basetypes.h"
#if defined( _WIN32 )
#pragma once
#endif
#define FUNC_APPEND_PARAMS_0
#define FUNC_APPEND_PARAMS_1 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 1 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) );
#define FUNC_APPEND_PARAMS_2 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 2 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) );
#define FUNC_APPEND_PARAMS_3 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 3 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) );
#define FUNC_APPEND_PARAMS_4 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 4 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) );
#define FUNC_APPEND_PARAMS_5 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 5 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) );
#define FUNC_APPEND_PARAMS_6 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 6 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) );
#define FUNC_APPEND_PARAMS_7 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 7 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) );
#define FUNC_APPEND_PARAMS_8 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 8 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) );
#define FUNC_APPEND_PARAMS_9 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 9 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) );
#define FUNC_APPEND_PARAMS_10 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 10 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) );
#define FUNC_APPEND_PARAMS_11 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 11 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) );
#define FUNC_APPEND_PARAMS_12 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 12 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_12 ) );
#define FUNC_APPEND_PARAMS_13 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 13 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_12 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_13 ) );
#define FUNC_APPEND_PARAMS_14 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 14 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_12 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_13 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_14 ) );
#define DEFINE_NONMEMBER_FUNC_TYPE_DEDUCER(N) \
template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
inline void ScriptDeduceFunctionSignature(ScriptFuncDescriptor_t *pDesc, FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \
{ \
pDesc->m_ReturnType = ScriptDeduceType(FUNCTION_RETTYPE); \
FUNC_APPEND_PARAMS_##N \
}
FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNC_TYPE_DEDUCER );
#define DEFINE_MEMBER_FUNC_TYPE_DEDUCER(N) \
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
inline void ScriptDeduceFunctionSignature(ScriptFuncDescriptor_t *pDesc, OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \
{ \
pDesc->m_ReturnType = ScriptDeduceType(FUNCTION_RETTYPE); \
FUNC_APPEND_PARAMS_##N \
}
FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNC_TYPE_DEDUCER );
//-------------------------------------
#define DEFINE_CONST_MEMBER_FUNC_TYPE_DEDUCER(N) \
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
inline void ScriptDeduceFunctionSignature(ScriptFuncDescriptor_t *pDesc, OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const ) \
{ \
pDesc->m_ReturnType = ScriptDeduceType(FUNCTION_RETTYPE); \
FUNC_APPEND_PARAMS_##N \
}
FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNC_TYPE_DEDUCER );
#define ScriptInitMemberFuncDescriptor_( pDesc, class, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, (class *)(0), &class::func ); }
#define ScriptInitFuncDescriptorNamed( pDesc, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, &func ); }
#define ScriptInitFuncDescriptor( pDesc, func ) ScriptInitFuncDescriptorNamed( pDesc, func, #func )
#define ScriptInitMemberFuncDescriptorNamed( pDesc, class, func, scriptName ) ScriptInitMemberFuncDescriptor_( pDesc, class, func, scriptName )
#define ScriptInitMemberFuncDescriptor( pDesc, class, func ) ScriptInitMemberFuncDescriptorNamed( pDesc, class, func, #func )
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
template <typename FUNCPTR_TYPE>
inline ScriptFunctionBindingStorageType_t ScriptConvertFreeFuncPtrToVoid( FUNCPTR_TYPE pFunc )
{
#if defined(_PS3) || defined(POSIX)
COMPILE_TIME_ASSERT( sizeof( FUNCPTR_TYPE ) == sizeof( void* ) * 2 || sizeof( FUNCPTR_TYPE ) == sizeof( void* ) );
if ( sizeof( FUNCPTR_TYPE ) == 4 )
{
union FuncPtrConvertMI
{
FUNCPTR_TYPE pFunc;
ScriptFunctionBindingStorageType_t stype;
};
FuncPtrConvertMI convert;
convert.pFunc = pFunc;
return convert.stype;
}
else
{
union FuncPtrConvertMI
{
FUNCPTR_TYPE pFunc;
struct
{
ScriptFunctionBindingStorageType_t stype;
intptr_t iToc;
} fn8;
};
FuncPtrConvertMI convert;
convert.fn8.iToc = 0;
convert.pFunc = pFunc;
if ( !convert.fn8.iToc )
return convert.fn8.stype;
Assert( 0 );
DebuggerBreak();
return 0;
}
#else
return ( ScriptFunctionBindingStorageType_t ) pFunc;
#endif
}
template <typename FUNCPTR_TYPE>
inline FUNCPTR_TYPE ScriptConvertFreeFuncPtrFromVoid( ScriptFunctionBindingStorageType_t p )
{
#if defined(_PS3) || defined(POSIX)
COMPILE_TIME_ASSERT( sizeof( FUNCPTR_TYPE ) == sizeof(void*)*2 || sizeof( FUNCPTR_TYPE ) == sizeof(void*) );
if ( sizeof( FUNCPTR_TYPE ) == 4 )
{
union FuncPtrConvertMI
{
FUNCPTR_TYPE pFunc;
ScriptFunctionBindingStorageType_t stype;
};
FuncPtrConvertMI convert;
convert.pFunc = 0;
convert.stype = p;
return convert.pFunc;
}
else
{
union FuncPtrConvertMI
{
FUNCPTR_TYPE pFunc;
struct
{
ScriptFunctionBindingStorageType_t stype;
intptr_t iToc;
} fn8;
};
FuncPtrConvertMI convert;
convert.pFunc = 0;
convert.fn8.stype = p;
convert.fn8.iToc = 0;
return convert.pFunc;
}
#else
return (FUNCPTR_TYPE) p;
#endif
}
template <typename FUNCPTR_TYPE>
inline ScriptFunctionBindingStorageType_t ScriptConvertFuncPtrToVoid( FUNCPTR_TYPE pFunc )
{
typedef FUNCPTR_TYPE FuncPtr_t;
size_t funcPtrSize = sizeof( FuncPtr_t ); funcPtrSize;
#if defined(_PS3) || defined(POSIX)
return ScriptConvertFreeFuncPtrToVoid<FUNCPTR_TYPE>( pFunc );
#else
if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) ) )
{
// simple inheritance
union FuncPtrConvert
{
void *p;
FUNCPTR_TYPE pFunc;
};
FuncPtrConvert convert;
convert.pFunc = pFunc;
return convert.p;
}
#if MSVC
else if ( ( IsPlatformWindowsPC32() && ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) ) ||
( IsPlatformWindowsPC64() && ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) * 2 ) ) )
{
// multiple and virtual inheritance
struct MicrosoftUnknownMFP
{
void *p;
int m_delta;
};
union FuncPtrConvertMI
{
MicrosoftUnknownMFP mfp;
FUNCPTR_TYPE pFunc;
};
FuncPtrConvertMI convert;
convert.pFunc = pFunc;
if ( convert.mfp.m_delta == 0 )
{
return convert.mfp.p;
}
AssertMsg( 0, "Function pointer must be from primary vtable" );
}
else if ( ( IsPlatformWindowsPC32() && ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + ( sizeof( int ) * 3 ) ) ) ||
( IsPlatformWindowsPC64() && ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + ( sizeof( int ) * 4 ) ) ) )
{
// unknown_inheritance case
struct MicrosoftUnknownMFP
{
void *p;
int m_delta;
int m_vtordisp;
int m_vtable_index;
};
union FuncPtrConvertMI
{
MicrosoftUnknownMFP mfp;
FUNCPTR_TYPE pFunc;
};
FuncPtrConvertMI convert;
convert.pFunc = pFunc;
if ( convert.mfp.m_delta == 0 )
{
return convert.mfp.p;
}
AssertMsg( 0, "Function pointer must be from primary vtable" );
}
#elif defined( GNUC )
else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) )
{
AssertMsg( 0, "Note: This path has not been verified yet. See comments below in #else case." );
struct GnuMFP
{
union
{
void *funcadr; // If vtable_index_2 is even, then this is the function pointer.
int vtable_index_2; // If vtable_index_2 is odd, then this = vindex*2+1.
};
int delta;
};
GnuMFP *p = (GnuMFP*)&pFunc;
if ( p->vtable_index_2 & 1 )
{
char **delta = (char**)p->delta;
char *pCur = *delta + (p->vtable_index_2+1)/2;
return (void*)( pCur + 4 );
}
else
{
return p->funcadr;
}
}
#else
#error "Need to implement code to crack non-offset member function pointer case"
// For gcc, see: http://www.codeproject.com/KB/cpp/FastDelegate.aspx
//
// Current versions of the GNU compiler use a strange and tricky
// optimization. It observes that, for virtual inheritance, you have to look
// up the vtable in order to get the voffset required to calculate the this
// pointer. While you're doing that, you might as well store the function
// pointer in the vtable. By doing this, they combine the m_func_address and
// m_vtable_index fields into one, and they distinguish between them by
// ensuring that function pointers always point to even addresses but vtable
// indices are always odd:
//
// // GNU g++ uses a tricky space optimisation, also adopted by IBM's VisualAge and XLC.
// struct GnuMFP {
// union {
// CODEPTR funcadr; // always even
// int vtable_index_2; // = vindex*2+1, always odd
// };
// int delta;
// };
// adjustedthis = this + delta
// if (funcadr & 1) CALL (* ( *delta + (vindex+1)/2) + 4)
// else CALL funcadr
//
// The G++ method is well documented, so it has been adopted by many other
// vendors, including IBM's VisualAge and XLC compilers, recent versions of
// Open64, Pathscale EKO, and Metrowerks' 64-bit compilers. A simpler scheme
// used by earlier versions of GCC is also very common. SGI's now
// discontinued MIPSPro and Pro64 compilers, and Apple's ancient MrCpp
// compiler used this method. (Note that the Pro64 compiler has become the
// open source Open64 compiler).
#endif
else
AssertMsg( 0, "Member function pointer not supported. Why on earth are you using virtual inheritance!?" );
return NULL;
#endif
}
template <typename FUNCPTR_TYPE>
inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( ScriptFunctionBindingStorageType_t p )
{
#if defined(_PS3) || defined(POSIX)
return ScriptConvertFreeFuncPtrFromVoid<FUNCPTR_TYPE>( p );
#else
if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) ) )
{
union FuncPtrConvert
{
void *p;
FUNCPTR_TYPE pFunc;
};
FuncPtrConvert convert;
convert.p = p;
return convert.pFunc;
}
#if MSVC
if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) )
{
struct MicrosoftUnknownMFP
{
void *p;
int m_delta;
};
union FuncPtrConvertMI
{
MicrosoftUnknownMFP mfp;
FUNCPTR_TYPE pFunc;
};
FuncPtrConvertMI convert;
convert.mfp.p = p;
convert.mfp.m_delta = 0;
return convert.pFunc;
}
if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + ( sizeof( int ) * 3 ) ) )
{
struct MicrosoftUnknownMFP
{
void *p;
int m_delta;
int m_vtordisp;
int m_vtable_index;
};
union FuncPtrConvertMI
{
MicrosoftUnknownMFP mfp;
FUNCPTR_TYPE pFunc;
};
FuncPtrConvertMI convert;
convert.mfp.p = p;
convert.mfp.m_delta = 0;
return convert.pFunc;
}
#elif defined( POSIX )
AssertMsg( 0, "Note: This path has not been implemented yet." );
#else
#error "Need to implement code to crack non-offset member function pointer case"
#endif
Assert( 0 );
return NULL;
#endif
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_0
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_1 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_1
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_2 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_2
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_3 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_3
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_4 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_4
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_5 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_5
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_6 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_6
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_7 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_7
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_8 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_8
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_9 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_9
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_10 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_10
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_11 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_11
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_12 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_12
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_13 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_13
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_14 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_14
#define SCRIPT_BINDING_ARGS_0
#define SCRIPT_BINDING_ARGS_1 pArguments[0]
#define SCRIPT_BINDING_ARGS_2 pArguments[0], pArguments[1]
#define SCRIPT_BINDING_ARGS_3 pArguments[0], pArguments[1], pArguments[2]
#define SCRIPT_BINDING_ARGS_4 pArguments[0], pArguments[1], pArguments[2], pArguments[3]
#define SCRIPT_BINDING_ARGS_5 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4]
#define SCRIPT_BINDING_ARGS_6 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5]
#define SCRIPT_BINDING_ARGS_7 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6]
#define SCRIPT_BINDING_ARGS_8 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7]
#define SCRIPT_BINDING_ARGS_9 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8]
#define SCRIPT_BINDING_ARGS_10 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9]
#define SCRIPT_BINDING_ARGS_11 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10]
#define SCRIPT_BINDING_ARGS_12 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10], pArguments[11]
#define SCRIPT_BINDING_ARGS_13 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10], pArguments[11], pArguments[12]
#define SCRIPT_BINDING_ARGS_14 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10], pArguments[11], pArguments[12], pArguments[13]
#define DEFINE_SCRIPT_BINDINGS(N) \
template <typename FUNC_TYPE, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
class CNonMemberScriptBinding##N \
{ \
public: \
static bool Call( ScriptFunctionBindingStorageType_t pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
{ \
Assert( nArguments == N ); \
Assert( pReturn ); \
Assert( !pContext ); \
\
if ( nArguments != N || !pReturn || pContext ) \
{ \
return false; \
} \
*pReturn = (ScriptConvertFreeFuncPtrFromVoid<FUNC_TYPE>(pFunction))( SCRIPT_BINDING_ARGS_##N ); \
if ( pReturn->m_type == FIELD_VECTOR ) \
pReturn->m_pVector = new Vector(*pReturn->m_pVector); \
return true; \
} \
}; \
\
template <typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
class CNonMemberScriptBinding##N<FUNC_TYPE, void FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
{ \
public: \
static bool Call( ScriptFunctionBindingStorageType_t pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
{ \
Assert( nArguments == N ); \
Assert( !pReturn ); \
Assert( !pContext ); \
\
if ( nArguments != N || pReturn || pContext ) \
{ \
return false; \
} \
(ScriptConvertFreeFuncPtrFromVoid<FUNC_TYPE>(pFunction))( SCRIPT_BINDING_ARGS_##N ); \
return true; \
} \
}; \
\
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
class CMemberScriptBinding##N \
{ \
public: \
static bool Call( ScriptFunctionBindingStorageType_t pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
{ \
Assert( nArguments == N ); \
Assert( pReturn ); \
Assert( pContext ); \
\
if ( nArguments != N || !pReturn || !pContext ) \
{ \
return false; \
} \
*pReturn = (((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid<FUNC_TYPE>(pFunction))( SCRIPT_BINDING_ARGS_##N ); \
if ( pReturn->m_type == FIELD_VECTOR ) \
pReturn->m_pVector = new Vector(*pReturn->m_pVector); \
return true; \
} \
}; \
\
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
class CMemberScriptBinding##N<OBJECT_TYPE_PTR, FUNC_TYPE, void FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
{ \
public: \
static bool Call( ScriptFunctionBindingStorageType_t pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
{ \
Assert( nArguments == N ); \
Assert( !pReturn ); \
Assert( pContext ); \
\
if ( nArguments != N || pReturn || !pContext ) \
{ \
return false; \
} \
(((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid<FUNC_TYPE>(pFunction))( SCRIPT_BINDING_ARGS_##N ); \
return true; \
} \
}; \
\
template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
inline ScriptBindingFunc_t ScriptCreateBinding(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \
{ \
typedef FUNCTION_RETTYPE (*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \
return &CNonMemberScriptBinding##N<Func_t, FUNCTION_RETTYPE FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N>::Call; \
} \
\
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
inline ScriptBindingFunc_t ScriptCreateBinding(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE (FUNCTION_CLASS::*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \
{ \
typedef FUNCTION_RETTYPE (FUNCTION_CLASS::*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \
return &CMemberScriptBinding##N<OBJECT_TYPE_PTR, Func_t, FUNCTION_RETTYPE FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N>::Call; \
} \
\
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
inline ScriptBindingFunc_t ScriptCreateBinding(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE (FUNCTION_CLASS::*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const ) \
{ \
typedef FUNCTION_RETTYPE (FUNCTION_CLASS::*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \
return &CMemberScriptBinding##N<OBJECT_TYPE_PTR, Func_t, FUNCTION_RETTYPE FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N>::Call; \
}
FUNC_GENERATE_ALL( DEFINE_SCRIPT_BINDINGS );
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
#endif // VSCRIPT_TEMPLATES_H