1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-09-19 03:56:10 +08:00

First version of the SOurce SDK 2013

This commit is contained in:
Joe Ludwig
2013-06-26 15:22:04 -07:00
commit e7d6f4c174
3682 changed files with 1624327 additions and 0 deletions

54
public/BitmapFontFile.h Normal file
View File

@ -0,0 +1,54 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Baked Bitmap fonts
//
//===========================================================================
#ifndef _BITMAPFONTFILE_H_
#define _BITMAPFONTFILE_H_
#include "datamap.h"
#define BITMAPFONT_ID (('T'<<24)|('N'<<16)|('F'<<8)|('V'))
#define BITMAPFONT_VERSION 3
// style flags
#define BF_BOLD 0x0001
#define BF_ITALIC 0x0002
#define BF_OUTLINED 0x0004
#define BF_DROPSHADOW 0x0008
#define BF_BLURRED 0x0010
#define BF_SCANLINES 0x0020
#define BF_ANTIALIASED 0x0040
#define BF_CUSTOM 0x0080
#pragma pack(1) //X360TBD
typedef struct BitmapGlyph_s
{
DECLARE_BYTESWAP_DATADESC();
short x;
short y;
short w;
short h;
short a;
short b;
short c;
} BitmapGlyph_t;
typedef struct BitmapFont_s
{
DECLARE_BYTESWAP_DATADESC();
int m_id;
int m_Version;
short m_PageWidth;
short m_PageHeight;
short m_MaxCharWidth;
short m_MaxCharHeight;
short m_Flags;
short m_Ascent;
short m_NumGlyphs;
unsigned char m_TranslateTable[256];
} BitmapFont_t;
#pragma pack()
#endif

103
public/Color.h Normal file
View File

@ -0,0 +1,103 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef COLOR_H
#define COLOR_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Basic handler for an rgb set of colors
// This class is fully inline
//-----------------------------------------------------------------------------
class Color
{
public:
// constructors
Color()
{
*((int *)this) = 0;
}
Color(int _r,int _g,int _b)
{
SetColor(_r, _g, _b, 0);
}
Color(int _r,int _g,int _b,int _a)
{
SetColor(_r, _g, _b, _a);
}
// set the color
// r - red component (0-255)
// g - green component (0-255)
// b - blue component (0-255)
// a - alpha component, controls transparency (0 - transparent, 255 - opaque);
void SetColor(int _r, int _g, int _b, int _a = 0)
{
_color[0] = (unsigned char)_r;
_color[1] = (unsigned char)_g;
_color[2] = (unsigned char)_b;
_color[3] = (unsigned char)_a;
}
void GetColor(int &_r, int &_g, int &_b, int &_a) const
{
_r = _color[0];
_g = _color[1];
_b = _color[2];
_a = _color[3];
}
void SetRawColor( int color32 )
{
*((int *)this) = color32;
}
int GetRawColor() const
{
return *((int *)this);
}
inline int r() const { return _color[0]; }
inline int g() const { return _color[1]; }
inline int b() const { return _color[2]; }
inline int a() const { return _color[3]; }
unsigned char &operator[](int index)
{
return _color[index];
}
const unsigned char &operator[](int index) const
{
return _color[index];
}
bool operator == (const Color &rhs) const
{
return ( *((int *)this) == *((int *)&rhs) );
}
bool operator != (const Color &rhs) const
{
return !(operator==(rhs));
}
Color &operator=( const Color &rhs )
{
SetRawColor( rhs.GetRawColor() );
return *this;
}
private:
unsigned char _color[4];
};
#endif // COLOR_H

View File

@ -0,0 +1,56 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef ADDONMESSAGES_H
#define ADDONMESSAGES_H
#pragma once
enum GameMessageIDs
{
GAME_MSG_TEXT = 1, // text chat message
GAME_MSG_DATA, // binary game data
GAME_MSG_INVITE_REQUEST,
GAME_MSG_INVITE_RESPONSE,
GAME_MSG_REJOIN_REQUEST,
GAME_MSG_REJOIN_RESPONSE,
GAME_MSG_INVITE_PERMISSION, // ask permission to invite someone
GAME_MSG_INVITE_NOTIFY, // tell everybody that we're inviting
GAME_MSG_INVITE_DENIED,
GAME_MSG_PLAYER_STATUS_UPDATE,
GAME_MSG_SETUP_INFO, // when user joins a game, host send the setup information of who's in the game
GAME_MSG_INVITE_CANCEL, // host has cancelled an invite
GAME_MSG_GAME_START, // if a game has a setup phase, this tells everybody the game has started
GAME_MSG_PLAYER_KICK, // player kicked from game
GAME_MSG_UPDATING,
GAME_MSG_UP_TO_DATE, // player is up to date and ready to get data
GAME_MSG_STARTING_CARD_HAND = 300,
GAME_MSG_STARTING_PLAYER,
GAME_MSG_CARD_PLAY,
GAME_MSG_CHEAT_POSSIBLE = 400, // when host detects a possible cheat
GAME_MSG_MOVE = 500,
GAME_MSG_COLOR_CHOICE,
GAME_MSG_RECONNECT_DATA,
GAME_MSG_QUIT,
GAME_MSG_PASS,
GAME_MSG_ABORT, // phase these out
GAME_MSG_WAITING_ABORT,
// GAME_MSG_CLOSE_WINDOW,
// special individual game messages should take IDs 1000 and over
};
#endif // ADDONMESSAGES_H

View File

@ -0,0 +1,18 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef ADDONTYPES_H
#define ADDONTYPES_H
#pragma once
#ifndef WIN32
typedef unsigned long long SessionInt64;
#else
typedef unsigned __int64 SessionInt64;
#endif
#endif // ADDONTYPES_H

View File

@ -0,0 +1,69 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interface to a Steam Add On
//
//=============================================================================//
#ifndef ISTEAMADDON_H
#define ISTEAMADDON_H
#pragma once
#include "interface.h"
#include "AddOnTypes.h"
#include <vgui_controls/Panel.h>
class CUtlMsgBuffer;
class ISteamAddOn : public IBaseInterface
{
public:
// allows SteamAddOn to link to the core vgui factories
virtual bool Initialize(CreateInterfaceFn *vguiFactories, int factoryCount) = 0;
// allows SteamAddOns to link to all other modules
virtual bool PostInitialize(CreateInterfaceFn *modules, int factoryCount) = 0;
// when Friends closes down - all SteamAddOns are notified
virtual void Deactivate() = 0;
// notifies the addon who its VGUI parent panel is
virtual void SetParent( vgui::Panel *parent ) = 0;
// notifies the SteamAddOn of the user's ID and username.
// Note: username can be set mulitple times due to changing of name
virtual void SetUserID(unsigned int userID) = 0;
virtual void SetUserName(const char *userName) = 0;
// Query if there are any 'open' sessions - open meaning allowing new users to join the sessions
virtual int QueryOpenSessionCount() = 0;
// will be valid right after a call to QueryOpenInviteCount will set the addOnSessionID and hostname for
// any open sessions for this addOn. Return true if it's a valid index
virtual bool QueryOpenSessionInfo(int nOpenGameIndex, SessionInt64 &addOnSessionID, char *pszHostName) = 0;
// returns true if this userID is involved in an addOnSession with this ID
virtual bool QueryUserInvolved(SessionInt64 addOnSessionID, unsigned int userID) = 0;
// if session doesn't exist, then the SteamAddOn body should deal with it
virtual bool OnReceiveMsg(SessionInt64 addOnSessionID, CUtlMsgBuffer *msgBuffer) = 0;
// Let's the SteamAddOn know when when any friend's status has changed
virtual void OnFriendStatusChanged() = 0;
// A request to start/join this AddOn with this user ID/name. addOnSessionID will be zero if it's a new session request
virtual void OnInviteUser(unsigned int targetUserID, const char *username, SessionInt64 addOnSessionID) = 0;
// user accepted this host's invite request
virtual void OnAcceptInviteRequest(unsigned int hostID, const char *hostUserName, SessionInt64 addOnSessionID, const char *pAppData, int dataLen) = 0;
// user accepted this host's rejoin request
virtual void OnAcceptRejoinRequest(unsigned int hostID, const char *hostUserName, SessionInt64 addOnSessionID, const char *pAppData, int dataLen) = 0;
// user starts this addOn from a menu
virtual void StartAddOn() = 0;
};
#define STEAMADDON_INTERFACE_VERSION "SteamAddOn007"
#endif // ISTEAMADDON_H

View File

@ -0,0 +1,41 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef FRIENDSNET_INTERFACE_H
#define FRIENDSNET_INTERFACE_H
#pragma once
class CUtlMsgBuffer;
class CServerSession;
#include "interface.h"
#include "Friends/AddOns/AddOnTypes.h"
class IFriendsNET : public IBaseInterface
{
public:
// check if we have network information for this user
virtual bool CheckUserRegistered(unsigned int userID) = 0;
// update a user's network information
virtual void UpdateUserNetInfo(unsigned int userID, unsigned int netSessionID, int serverID, int IP, int port) = 0;
// set whether or not we send directly to user or through the server
virtual void SetUserSendViaServer(unsigned int userID, bool bSendViaServer) = 0;
// Gets a blob of data that represents this user's information
virtual bool GetUserNetInfoBlob(unsigned int userID, unsigned int dataBlob[8]) = 0;
// Sets a user's information using the same blob of data type
virtual bool SetUserNetInfoBlob(unsigned int userID, const unsigned int dataBlob[8]) = 0;
// send binary data to user, marked with game/sessionID
virtual void SendAddOnPacket(const char *pszGameID, SessionInt64 addOnSessionID, unsigned int userID, const CUtlMsgBuffer& buffer) = 0;
};
#define FRIENDSNET_INTERFACE_VERSION "FriendsNET003"
#endif // FRIENDSNET_INTERFACE_H

View File

@ -0,0 +1,62 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef IFRIENDSUSER_H
#define IFRIENDSUSER_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
//-----------------------------------------------------------------------------
// Purpose: Interface to accessing information about Friends Users
//-----------------------------------------------------------------------------
class IFriendsUser : public IBaseInterface
{
public:
// returns true if the interface is ready for use
virtual bool IsValid() = 0;
// returns the Friends ID of the current user
virtual unsigned int GetFriendsID() = 0;
// returns information about a user
// information may not be known about some users, "" will be returned
virtual const char *GetUserName(unsigned int friendsID) = 0;
virtual const char *GetFirstName(unsigned int friendsID) = 0;
virtual const char *GetLastName(unsigned int friendsID) = 0;
virtual const char *GetEmail(unsigned int friendsID) = 0;
// returns true if buddyID is a buddy of the current user
// ie. the current is authorized to see when the buddy is online
virtual bool IsBuddy(unsigned int buddyID) = 0;
// requests authorization from a user
virtual void RequestAuthorizationFromUser(unsigned int potentialBuddyID) = 0;
// returns the status of the buddy, > 0 is online, 4 is ingame
virtual int GetBuddyStatus(unsigned int friendsID) = 0;
// gets the IP address of the server the buddy is on, returns false if couldn't get
virtual bool GetBuddyGameAddress(unsigned int friendsID, int *ip, int *port) = 0;
// returns the number of buddies
virtual int GetNumberOfBuddies() = 0;
// returns the FriendsID of a buddy - buddyIndex is valid in the range [0, GetNumberOfBuddies)
virtual unsigned int GetBuddyFriendsID(int buddyIndex) = 0;
// sets whether or not the user can receive messages at this time
// messages will be queued until this is set to true
virtual void SetCanReceiveMessages(bool state) = 0;
};
#define FRIENDSUSER_INTERFACE_VERSION "FriendsUser001"
#endif // IFRIENDSUSER_H

30
public/IGameUIFuncs.h Normal file
View File

@ -0,0 +1,30 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef IGAMEUIFUNCS_H
#define IGAMEUIFUNCS_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui/KeyCode.h"
abstract_class IGameUIFuncs
{
public:
virtual bool IsKeyDown( const char *keyname, bool& isdown ) = 0;
virtual const char *GetBindingForButtonCode( ButtonCode_t code ) = 0;
virtual ButtonCode_t GetButtonCodeForBind( const char *pBind ) = 0;
virtual void GetVideoModes( struct vmode_s **liststart, int *count ) = 0;
virtual void SetFriendsID( uint friendsID, const char *friendsName ) = 0;
virtual void GetDesktopResolution( int &width, int &height ) = 0;
virtual bool IsConnectedToVACSecureServer() = 0;
};
#define VENGINE_GAMEUIFUNCS_VERSION "VENGINE_GAMEUIFUNCS_VERSION005"
#endif // IGAMEUIFUNCS_H

56
public/IHammer.h Normal file
View File

@ -0,0 +1,56 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: The application object.
//
//=============================================================================//
#ifndef IHAMMER_H
#define IHAMMER_H
#include "appframework/IAppSystem.h"
typedef struct tagMSG MSG;
class IStudioDataCache;
//-----------------------------------------------------------------------------
// Return values for RequestNewConfig
//-----------------------------------------------------------------------------
enum RequestRetval_t
{
REQUEST_OK = 0,
REQUEST_QUIT
};
//-----------------------------------------------------------------------------
// Interface used to drive hammer
//-----------------------------------------------------------------------------
#define INTERFACEVERSION_HAMMER "Hammer001"
class IHammer : public IAppSystem
{
public:
virtual bool HammerPreTranslateMessage( MSG * pMsg ) = 0;
virtual bool HammerIsIdleMessage( MSG * pMsg ) = 0;
virtual bool HammerOnIdle( long count ) = 0;
virtual void RunFrame() = 0;
// Returns the mod and the game to initially start up
virtual const char *GetDefaultMod() = 0;
virtual const char *GetDefaultGame() = 0;
virtual bool InitSessionGameConfig( const char *szGameDir ) = 0;
// Request a new config from hammer's config system
virtual RequestRetval_t RequestNewConfig() = 0;
// Returns the full path to the mod and the game to initially start up
virtual const char *GetDefaultModFullPath() = 0;
virtual int MainLoop() = 0;
};
#endif // IHAMMER_H

29
public/OfflineMode.h Normal file
View File

@ -0,0 +1,29 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include <vgui/ISystem.h>
#include <vgui_controls/Controls.h>
#define STEAM_OFFLINE_MODE "HKEY_CURRENT_USER\\Software\\Valve\\Steam\\Offline"
#define STEAM_AFS_MODE "HKEY_CURRENT_USER\\Software\\Valve\\Steam\\OfflineAFS"
#define OFFLINE_FILE "Steam\\cached\\offline_" // first part of filename
inline bool IsSteamInOfflineMode()
{
int offline = 0;
vgui::system()->GetRegistryInteger( STEAM_OFFLINE_MODE, offline );
return ( offline == 1 );
}inline bool IsSteamInAuthenticationFailSafeMode()
{
int offline = 0;
vgui::system()->GetRegistryInteger( STEAM_AFS_MODE, offline );
return ( offline == 1 );
}
inline bool IsSteamGameServerBrowsingEnabled()
{
return (IsSteamInAuthenticationFailSafeMode() || !IsSteamInOfflineMode());
}

63
public/PlayerState.h Normal file
View File

@ -0,0 +1,63 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef PLAYERSTATE_H
#define PLAYERSTATE_H
#ifdef _WIN32
#pragma once
#endif
#include "edict.h"
#include "networkvar.h"
// Only care about this stuff in game/client .dlls
#if defined( CLIENT_DLL )
#include "predictable_entity.h"
#endif
class CPlayerState
{
public:
DECLARE_CLASS_NOBASE( CPlayerState );
DECLARE_EMBEDDED_NETWORKVAR();
// This virtual method is necessary to generate a vtable in all cases
// (DECLARE_PREDICTABLE will generate a vtable also)!
virtual ~CPlayerState() {}
// true if the player is dead
CNetworkVar( bool, deadflag );
// Viewing angle (player only)
QAngle v_angle;
// The client .dll only cares about deadflag
// the game and engine .dlls need to worry about the rest of this data
#if !defined( CLIENT_DLL )
// Player's network name
string_t netname;
// 0:nothing, 1:force view angles, 2:add avelocity
int fixangle;
// delta angle for fixangle == FIXANGLE_RELATIVE
QAngle anglechange;
// flag to single the HLTV/Replay fake client, not transmitted
bool hltv;
bool replay;
int frags;
int deaths;
#endif
// NOTE: Only care about this stuff in game/client dlls
// Put at end in case it has any effect on size of structure
#if defined( GAME_DLL )
DECLARE_SIMPLE_DATADESC();
#endif
#if defined( CLIENT_DLL )
DECLARE_PREDICTABLE();
#endif
};
#endif // PLAYERSTATE_H

467
public/ScratchPadUtils.cpp Normal file
View File

@ -0,0 +1,467 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#if !defined(_STATIC_LINKED) || defined(_SHARED_LIB)
#include "iscratchpad3d.h"
#include "mathlib/mathlib.h"
#include "ScratchPadUtils.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// --------------------------------------------------------------------------------------------------------------------- //
// CScratchPadGraph implementation.
// --------------------------------------------------------------------------------------------------------------------- //
CScratchPadGraph::CScratchPadGraph()
{
m_pPad = NULL;
}
void CScratchPadGraph::Init(
IScratchPad3D *pPad,
Vector vTimeAxis,
float flInchesPerSecond,
Vector vTimeLineColor,
float flTimeOrigin,
float flTimeLabelEveryNSeconds,
Vector vValueAxis,
float flInchesPerValue,
Vector vValueLineColor,
float flValueOrigin
)
{
m_pPad = pPad;
m_vTimeAxis = vTimeAxis;
m_flInchesPerSecond = flInchesPerSecond;
m_vValueAxis = vValueAxis;
m_flInchesPerValue = flInchesPerValue;
m_flTimeLabelEveryNSeconds = flTimeLabelEveryNSeconds;
m_vTimeLineColor = vTimeLineColor;
m_vValueLineColor = vValueLineColor;
m_flTimeOrigin = flTimeOrigin;
m_flValueOrigin = flValueOrigin;
m_nTimeLabelsDrawn = 0;
m_flHighestTime = flTimeOrigin;
m_flHighestValue = flValueOrigin;
}
bool CScratchPadGraph::IsInitted() const
{
return m_pPad != NULL;
}
CScratchPadGraph::LineID CScratchPadGraph::AddLine( Vector vColor )
{
CScratchPadGraph::CLineInfo info;
info.m_bFirst = true;
info.m_vColor = vColor;
return m_LineInfos.AddToTail( info );
}
void CScratchPadGraph::AddSample( LineID iLine, float flTime, float flValue )
{
CScratchPadGraph::CLineInfo *pInfo = &m_LineInfos[iLine];
UpdateTicksAndStuff( flTime, flValue );
if ( !pInfo->m_bFirst )
{
// Draw a line from the last value to the current one.
Vector vStart = GetSamplePosition( pInfo->m_flLastTime, pInfo->m_flLastValue );
Vector vEnd = GetSamplePosition( flTime, flValue );
m_pPad->DrawLine(
CSPVert( vStart, pInfo->m_vColor ),
CSPVert( vEnd, pInfo->m_vColor )
);
}
pInfo->m_flLastTime = flTime;
pInfo->m_flLastValue = flValue;
pInfo->m_bFirst = false;
}
void CScratchPadGraph::AddVerticalLine( float flTime, float flMinValue, float flMaxValue, const CSPColor &vColor )
{
Vector v1 = GetSamplePosition( flTime, flMinValue );
Vector v2 = GetSamplePosition( flTime, flMaxValue );
m_pPad->DrawLine(
CSPVert( v1, vColor ),
CSPVert( v2, vColor ) );
}
void CScratchPadGraph::UpdateTicksAndStuff( float flTime, float flValue )
{
if ( flTime > m_flHighestTime )
{
// Update the left part of the time axis.
Vector vStart = GetSamplePosition( m_flHighestTime, m_flValueOrigin );
Vector vEnd = GetSamplePosition( flTime, m_flValueOrigin );
m_pPad->DrawLine(
CSPVert( vStart, m_vTimeLineColor ),
CSPVert( vEnd, m_vTimeLineColor )
);
m_flHighestTime = flTime;
}
if ( flValue > m_flHighestValue )
{
// Update the left part of the time axis.
Vector vStart = GetSamplePosition( m_flTimeOrigin, m_flHighestValue );
Vector vEnd = GetSamplePosition( m_flTimeOrigin, flValue );
m_pPad->DrawLine(
CSPVert( vStart, m_vValueLineColor ),
CSPVert( vEnd, m_vValueLineColor )
);
// Extend the lines attached to the time labels.
for ( int i=0; i < m_nTimeLabelsDrawn; i++ )
{
float flTime = m_flTimeOrigin + m_nTimeLabelsDrawn * m_flTimeLabelEveryNSeconds;
m_pPad->DrawLine(
CSPVert((const Vector&) GetSamplePosition( flTime, m_flHighestValue )),
CSPVert((const Vector&) GetSamplePosition( flTime, flValue ) )
);
}
m_flHighestValue = flValue;
}
// More text labels?
int iHighestTextLabel = (int)ceil( (flTime - m_flTimeOrigin) / m_flTimeLabelEveryNSeconds + 0.5f );
while ( m_nTimeLabelsDrawn < iHighestTextLabel )
{
CTextParams params;
float flTime = m_flTimeOrigin + m_nTimeLabelsDrawn * m_flTimeLabelEveryNSeconds;
params.m_bSolidBackground = true;
params.m_vPos = GetSamplePosition( flTime, m_flValueOrigin-5 );
params.m_bTwoSided = true;
char str[512];
Q_snprintf( str, sizeof( str ), "time: %.2f", flTime );
m_pPad->DrawText( str, params );
// Now draw the vertical line for the value..
m_pPad->DrawLine(
CSPVert( (const Vector&)GetSamplePosition( flTime, m_flValueOrigin ) ),
CSPVert( (const Vector&)GetSamplePosition( flTime, m_flHighestValue ) )
);
m_nTimeLabelsDrawn++;
}
}
Vector CScratchPadGraph::GetSamplePosition( float flTime, float flValue )
{
Vector vRet =
m_vTimeAxis * ((flTime - m_flTimeOrigin) * m_flInchesPerSecond) +
m_vValueAxis * ((flValue - m_flValueOrigin) * m_flInchesPerValue);
return vRet;
}
// --------------------------------------------------------------------------------------------------------------------- //
// Global functions.
// --------------------------------------------------------------------------------------------------------------------- //
void ScratchPad_DrawLitCone(
IScratchPad3D *pPad,
const Vector &vBaseCenter,
const Vector &vTip,
const Vector &vBrightColor,
const Vector &vDarkColor,
const Vector &vLightDir,
float baseWidth,
int nSegments )
{
// Make orthogonal vectors.
Vector vDir = vTip - vBaseCenter;
VectorNormalize( vDir );
Vector vRight, vUp;
VectorVectors( vDir, vRight, vUp );
vRight *= baseWidth;
vUp *= baseWidth;
// Setup the top and bottom caps.
CSPVertList bottomCap, tri;
bottomCap.m_Verts.SetSize( nSegments );
tri.m_Verts.SetSize( 3 );
float flDot = -vLightDir.Dot( vDir );
Vector topColor, bottomColor;
VectorLerp( vDarkColor, vBrightColor, RemapVal( -flDot, -1, 1, 0, 1 ), bottomColor );
// Draw each quad.
Vector vPrevBottom = vBaseCenter + vRight;
for ( int i=0; i < nSegments; i++ )
{
float flAngle = (float)(i+1) * M_PI * 2.0 / nSegments;
Vector vOffset = vRight * cos( flAngle ) + vUp * sin( flAngle );
Vector vCurBottom = vBaseCenter + vOffset;
const Vector &v1 = vTip;
const Vector &v2 = vPrevBottom;
const Vector &v3 = vCurBottom;
Vector vFaceNormal = (v2 - v1).Cross( v3 - v1 );
VectorNormalize( vFaceNormal );
// Now light it.
flDot = -vLightDir.Dot( vFaceNormal );
Vector vColor;
VectorLerp( vDarkColor, vBrightColor, RemapVal( flDot, -1, 1, 0, 1 ), vColor );
// Draw the quad.
tri.m_Verts[0] = CSPVert( v1, vColor );
tri.m_Verts[1] = CSPVert( v2, vColor );
tri.m_Verts[2] = CSPVert( v3, vColor );
pPad->DrawPolygon( tri );
bottomCap.m_Verts[i] = CSPVert( vCurBottom, bottomColor );
}
pPad->DrawPolygon( bottomCap );
}
void ScratchPad_DrawLitCylinder(
IScratchPad3D *pPad,
const Vector &v1,
const Vector &v2,
const Vector &vBrightColor,
const Vector &vDarkColor,
const Vector &vLightDir,
float width,
int nSegments )
{
// Make orthogonal vectors.
Vector vDir = v2 - v1;
VectorNormalize( vDir );
Vector vRight, vUp;
VectorVectors( vDir, vRight, vUp );
vRight *= width;
vUp *= width;
// Setup the top and bottom caps.
CSPVertList topCap, bottomCap, quad;
topCap.m_Verts.SetSize( nSegments );
bottomCap.m_Verts.SetSize( nSegments );
quad.m_Verts.SetSize( 4 );
float flDot = -vLightDir.Dot( vDir );
Vector topColor, bottomColor;
VectorLerp( vDarkColor, vBrightColor, RemapVal( flDot, -1, 1, 0, 1 ), topColor );
VectorLerp( vDarkColor, vBrightColor, RemapVal( -flDot, -1, 1, 0, 1 ), bottomColor );
// Draw each quad.
Vector vPrevTop = v1 + vRight;
Vector vPrevBottom = v2 + vRight;
for ( int i=0; i < nSegments; i++ )
{
float flAngle = (float)(i+1) * M_PI * 2.0 / nSegments;
Vector vOffset = vRight * cos( flAngle ) + vUp * sin( flAngle );
Vector vCurTop = v1 + vOffset;
Vector vCurBottom = v2 + vOffset;
// Now light it.
VectorNormalize( vOffset );
flDot = -vLightDir.Dot( vOffset );
Vector vColor;
VectorLerp( vDarkColor, vBrightColor, RemapVal( flDot, -1, 1, 0, 1 ), vColor );
// Draw the quad.
quad.m_Verts[0] = CSPVert( vPrevTop, vColor );
quad.m_Verts[1] = CSPVert( vPrevBottom, vColor );
quad.m_Verts[2] = CSPVert( vCurBottom, vColor );
quad.m_Verts[3] = CSPVert( vCurTop, vColor );
pPad->DrawPolygon( quad );
topCap.m_Verts[i] = CSPVert( vCurTop, topColor );
bottomCap.m_Verts[i] = CSPVert( vCurBottom, bottomColor );
}
pPad->DrawPolygon( topCap );
pPad->DrawPolygon( bottomCap );
}
void ScratchPad_DrawArrow(
IScratchPad3D *pPad,
const Vector &vPos,
const Vector &vDirection,
const Vector &vColor,
float flLength,
float flLineWidth,
float flHeadWidth,
int nCylinderSegments,
int nHeadSegments,
float flArrowHeadPercentage
)
{
Vector vNormDir = vDirection;
VectorNormalize( vNormDir );
Vector vConeBase = vPos + vNormDir * (flLength * ( 1 - flArrowHeadPercentage ) );
Vector vConeEnd = vPos + vNormDir * flLength;
Vector vLightDir( -1, -1, -1 );
VectorNormalize( vLightDir ); // could precalculate this
pPad->SetRenderState( IScratchPad3D::RS_FillMode, IScratchPad3D::FillMode_Solid );
pPad->SetRenderState( IScratchPad3D::RS_ZRead, true );
ScratchPad_DrawLitCylinder( pPad, vPos, vConeBase, vColor, vColor*0.25f, vLightDir, flLineWidth, nCylinderSegments );
ScratchPad_DrawLitCone( pPad, vConeBase, vConeEnd, vColor, vColor*0.25f, vLightDir, flHeadWidth, nHeadSegments );
}
void ScratchPad_DrawArrowSimple(
IScratchPad3D *pPad,
const Vector &vPos,
const Vector &vDirection,
const Vector &vColor,
float flLength )
{
ScratchPad_DrawArrow(
pPad,
vPos,
vDirection,
vColor,
flLength,
flLength * 1.0/15,
flLength * 3.0/15,
4,
4 );
}
void ScratchPad_DrawSphere(
IScratchPad3D *pPad,
const Vector &vCenter,
float flRadius,
const Vector &vColor,
int nSubDivs )
{
CUtlVector<Vector> prevPoints;
prevPoints.SetSize( nSubDivs );
// For each vertical slice.. (the top and bottom ones are just a single point).
for ( int iSlice=0; iSlice < nSubDivs; iSlice++ )
{
float flHalfSliceAngle = M_PI * (float)iSlice / (nSubDivs - 1);
if ( iSlice == 0 )
{
prevPoints[0] = vCenter + Vector( 0, 0, flRadius );
for ( int z=1; z < prevPoints.Count(); z++ )
prevPoints[z] = prevPoints[0];
}
else
{
for ( int iSubPt=0; iSubPt < nSubDivs; iSubPt++ )
{
float flHalfAngle = M_PI * (float)iSubPt / (nSubDivs - 1);
float flAngle = flHalfAngle * 2;
Vector pt;
if ( iSlice == (nSubDivs - 1) )
{
pt = vCenter - Vector( 0, 0, flRadius );
}
else
{
pt.x = cos( flAngle ) * sin( flHalfSliceAngle );
pt.y = sin( flAngle ) * sin( flHalfSliceAngle );
pt.z = cos( flHalfSliceAngle );
pt *= flRadius;
pt += vCenter;
}
pPad->DrawLine( CSPVert( pt, vColor ), CSPVert( prevPoints[iSubPt], vColor ) );
prevPoints[iSubPt] = pt;
}
if ( iSlice != (nSubDivs - 1) )
{
for ( int i=0; i < nSubDivs; i++ )
pPad->DrawLine( CSPVert( prevPoints[i], vColor ), CSPVert( prevPoints[(i+1)%nSubDivs], vColor ) );
}
}
}
}
void ScratchPad_DrawAABB(
IScratchPad3D *pPad,
const Vector &vMins,
const Vector &vMaxs,
const Vector &vColor )
{
int vertOrder[4][2] = {{0,0},{1,0},{1,1},{0,1}};
const Vector *vecs[2] = {&vMins, &vMaxs};
Vector vTop, vBottom, vPrevTop, vPrevBottom;
vTop.z = vPrevTop.z = vMaxs.z;
vBottom.z = vPrevBottom.z = vMins.z;
vPrevTop.x = vPrevBottom.x = vecs[vertOrder[3][0]]->x;
vPrevTop.y = vPrevBottom.y = vecs[vertOrder[3][1]]->y;
for ( int i=0; i < 4; i++ )
{
vTop.x = vBottom.x = vecs[vertOrder[i][0]]->x;
vTop.y = vBottom.y = vecs[vertOrder[i][1]]->y;
// Draw the top line.
pPad->DrawLine( CSPVert( vPrevTop, vColor ), CSPVert( vTop, vColor ) );
pPad->DrawLine( CSPVert( vPrevBottom, vColor ), CSPVert( vBottom, vColor ) );
pPad->DrawLine( CSPVert( vTop, vColor ), CSPVert( vBottom, vColor ) );
vPrevTop = vTop;
vPrevBottom = vBottom;
}
}
#endif // !_STATIC_LINKED || _SHARED_LIB

163
public/ScratchPadUtils.h Normal file
View File

@ -0,0 +1,163 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: This module contains helper functions for use with scratch pads.
//
// $NoKeywords: $
//=============================================================================//
#ifndef SCRATCHPADUTILS_H
#define SCRATCHPADUTILS_H
#ifdef _WIN32
#pragma once
#endif
#include "iscratchpad3d.h"
// Use this to make a graph.
class CScratchPadGraph
{
public:
typedef int LineID;
CScratchPadGraph();
// Initialze the orientation and scales of the two axes.
// Axis indices are 0, 1, or 2 for x, y, and z.
void Init(
IScratchPad3D *pPad,
Vector vTimeAxis = Vector(0,-1,0),
float flInchesPerSecond=1,
Vector vTimeLineColor=Vector(0,0,1),
float flTimeOrigin=0, // Where the origin of the graph is.
float flTimeLabelEveryNSeconds=1,
Vector vValueAxis = Vector(0,0,1),
float flInchesPerValue=1,
Vector vValueLineColor=Vector(1,0,0),
float flValueOrigin=0 // Where the origin of the graph is.
);
bool IsInitted() const;
// Add another line into the graph.
LineID AddLine( Vector vColor );
void AddSample( LineID iLine, float flTime, float flValue );
void AddVerticalLine( float flTime, float flMinValue, float flMaxValue, const CSPColor &vColor );
// Get the 3D position of a sample on the graph (so you can draw other things there).
Vector GetSamplePosition( float flTime, float flValue );
private:
void UpdateTicksAndStuff( float flTime, float flValue );
private:
class CLineInfo
{
public:
bool m_bFirst;
float m_flLastTime;
float m_flLastValue;
Vector m_vColor;
};
IScratchPad3D *m_pPad;
CUtlVector<CLineInfo> m_LineInfos;
Vector m_vTimeAxis;
float m_flInchesPerSecond;
Vector m_vValueAxis;
float m_flInchesPerValue;
// How often to make a time label.
float m_flTimeLabelEveryNSeconds;
int m_nTimeLabelsDrawn;
Vector m_vTimeLineColor;
Vector m_vValueLineColor;
float m_flTimeOrigin;
float m_flValueOrigin;
// Used to extend the value border.
float m_flHighestValue;
float m_flHighestTime;
};
// Draw a cone.
void ScratchPad_DrawLitCone(
IScratchPad3D *pPad,
const Vector &vBaseCenter,
const Vector &vTip,
const Vector &vBrightColor,
const Vector &vDarkColor,
const Vector &vLightDir,
float baseWidth,
int nSegments );
// Draw a cylinder.
void ScratchPad_DrawLitCylinder(
IScratchPad3D *pPad,
const Vector &v1,
const Vector &v2,
const Vector &vBrightColor,
const Vector &vDarkColor,
const Vector &vLightDir,
float width,
int nSegments );
// Draw an arrow.
void ScratchPad_DrawArrow(
IScratchPad3D *pPad,
const Vector &vPos,
const Vector &vDirection,
const Vector &vColor,
float flLength=20,
float flLineWidth=3,
float flHeadWidth=8,
int nCylinderSegments=5,
int nHeadSegments=8,
float flArrowHeadPercentage = 0.3f // How much of the line is the arrow head.
);
// Draw an arrow with less parameters.. it generates parameters based on length
// automatically to make the arrow look good.
void ScratchPad_DrawArrowSimple(
IScratchPad3D *pPad,
const Vector &vPos,
const Vector &vDirection,
const Vector &vColor,
float flLength );
void ScratchPad_DrawSphere(
IScratchPad3D *pPad,
const Vector &vCenter,
float flRadius,
const Vector &vColor,
int nSubDivs=7 );
void ScratchPad_DrawAABB(
IScratchPad3D *pPad,
const Vector &vMins,
const Vector &vMaxs,
const Vector &vColor = Vector( 1,1,1 ) );
#endif // SCRATCHPADUTILS_H

View File

@ -0,0 +1,269 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef ISOUNDEMITTERSYSTEMBASE_H
#define ISOUNDEMITTERSYSTEMBASE_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utldict.h"
#include "vstdlib/random.h"
#include "soundflags.h"
#include "mathlib/compressed_vector.h"
#include "appframework/IAppSystem.h"
#define SOUNDEMITTERSYSTEM_INTERFACE_VERSION "VSoundEmitter002"
#define SOUNDGENDER_MACRO "$gender"
#define SOUNDGENDER_MACRO_LENGTH 7 // Length of above including $
typedef short HSOUNDSCRIPTHANDLE;
#define SOUNDEMITTER_INVALID_HANDLE (HSOUNDSCRIPTHANDLE)-1
class IFileList;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
struct CSoundParameters
{
CSoundParameters()
{
channel = CHAN_AUTO; // 0
volume = VOL_NORM; // 1.0f
pitch = PITCH_NORM; // 100
pitchlow = PITCH_NORM;
pitchhigh = PITCH_NORM;
soundlevel = SNDLVL_NORM; // 75dB
soundname[ 0 ] = 0;
play_to_owner_only = false;
count = 0;
delay_msec = 0;
}
int channel;
float volume;
int pitch;
int pitchlow, pitchhigh;
soundlevel_t soundlevel;
// For weapon sounds...
bool play_to_owner_only;
int count;
char soundname[ 128 ];
int delay_msec;
};
// A bit of a hack, but these are just utility function which are implemented in the SouneParametersInternal.cpp file which all users of this lib also compile
const char *SoundLevelToString( soundlevel_t level );
const char *ChannelToString( int channel );
const char *VolumeToString( float volume );
const char *PitchToString( float pitch );
soundlevel_t TextToSoundLevel( const char *key );
int TextToChannel( const char *name );
enum gender_t
{
GENDER_NONE = 0,
GENDER_MALE,
GENDER_FEMALE,
};
#pragma pack(1)
struct SoundFile
{
SoundFile()
{
symbol = UTL_INVAL_SYMBOL;
gender = GENDER_NONE;
available = true;
COMPILE_TIME_ASSERT( sizeof(SoundFile) == 4 );
}
CUtlSymbol symbol;
byte gender;
byte available;
};
#pragma pack()
#pragma pack(1)
template<typename T>
struct sound_interval_t
{
T start;
T range;
interval_t &ToInterval( interval_t &dest ) const { dest.start = start; dest.range = range; return dest; }
void FromInterval( const interval_t &from ) { start = from.start; range = from.range; }
float Random() const { return RandomFloat( start, start + range ); }
};
#pragma pack()
typedef sound_interval_t<float16_with_assign> volume_interval_t;
typedef sound_interval_t<uint16> soundlevel_interval_t;
typedef sound_interval_t<uint8> pitch_interval_t;
#pragma pack(1)
struct CSoundParametersInternal
{
CSoundParametersInternal();
~CSoundParametersInternal();
void CopyFrom( const CSoundParametersInternal& src );
bool operator == ( const CSoundParametersInternal& other ) const;
const char *VolumeToString( void ) const;
const char *ChannelToString( void ) const;
const char *SoundLevelToString( void ) const;
const char *PitchToString( void ) const;
void VolumeFromString( const char *sz );
void ChannelFromString( const char *sz );
void PitchFromString( const char *sz );
void SoundLevelFromString( const char *sz );
int GetChannel() const { return channel; }
const volume_interval_t &GetVolume() const { return volume; }
const pitch_interval_t &GetPitch() const { return pitch; }
const soundlevel_interval_t &GetSoundLevel() const { return soundlevel; }
int GetDelayMsec() const { return delay_msec; }
bool OnlyPlayToOwner() const { return play_to_owner_only; }
bool HadMissingWaveFiles() const { return had_missing_wave_files; }
bool UsesGenderToken() const { return uses_gender_token; }
bool ShouldPreload() const { return m_bShouldPreload; }
void SetChannel( int newChannel ) { channel = newChannel; }
void SetVolume( float start, float range = 0.0 ) { volume.start = start; volume.range = range; }
void SetPitch( float start, float range = 0.0 ) { pitch.start = start; pitch.range = range; }
void SetSoundLevel( float start, float range = 0.0 ) { soundlevel.start = start; soundlevel.range = range; }
void SetDelayMsec( int delay ) { delay_msec = delay; }
void SetShouldPreload( bool bShouldPreload ) { m_bShouldPreload = bShouldPreload; }
void SetOnlyPlayToOwner( bool b ) { play_to_owner_only = b; }
void SetHadMissingWaveFiles( bool b ) { had_missing_wave_files = b; }
void SetUsesGenderToken( bool b ) { uses_gender_token = b; }
void AddSoundName( const SoundFile &soundFile ) { AddToTail( &m_pSoundNames, &m_nSoundNames, soundFile ); }
int NumSoundNames() const { return m_nSoundNames; }
SoundFile * GetSoundNames() { return ( m_nSoundNames == 1 ) ? (SoundFile *)&m_pSoundNames : m_pSoundNames; }
const SoundFile *GetSoundNames() const { return ( m_nSoundNames == 1 ) ? (SoundFile *)&m_pSoundNames : m_pSoundNames; }
void AddConvertedName( const SoundFile &soundFile ) { AddToTail( &m_pConvertedNames, &m_nConvertedNames, soundFile ); }
int NumConvertedNames() const { return m_nConvertedNames; }
SoundFile * GetConvertedNames() { return ( m_nConvertedNames == 1 ) ? (SoundFile *)&m_pConvertedNames : m_pConvertedNames; }
const SoundFile *GetConvertedNames() const { return ( m_nConvertedNames == 1 ) ? (SoundFile *)&m_pConvertedNames : m_pConvertedNames; }
private:
void operator=( const CSoundParametersInternal& src ); // disallow implicit copies
CSoundParametersInternal( const CSoundParametersInternal& src );
void AddToTail( SoundFile **pDest, uint16 *pDestCount, const SoundFile &source );
SoundFile * m_pSoundNames; // 4
SoundFile * m_pConvertedNames; // 8
uint16 m_nSoundNames; // 10
uint16 m_nConvertedNames; // 12
volume_interval_t volume; // 16
soundlevel_interval_t soundlevel; // 20
pitch_interval_t pitch; // 22
uint16 channel; // 24
uint16 delay_msec; // 26
bool play_to_owner_only:1; // For weapon sounds... // 27
// Internal use, for warning about missing .wav files
bool had_missing_wave_files:1;
bool uses_gender_token:1;
bool m_bShouldPreload:1;
byte reserved; // 28
};
#pragma pack()
//-----------------------------------------------------------------------------
// Purpose: Base class for sound emitter system handling (can be used by tools)
//-----------------------------------------------------------------------------
abstract_class ISoundEmitterSystemBase : public IAppSystem
{
public:
// Init, shutdown called after we know what mod is running
virtual bool ModInit() = 0;
virtual void ModShutdown() = 0;
virtual int GetSoundIndex( const char *pName ) const = 0;
virtual bool IsValidIndex( int index ) = 0;
virtual int GetSoundCount( void ) = 0;
virtual const char *GetSoundName( int index ) = 0;
virtual bool GetParametersForSound( const char *soundname, CSoundParameters& params, gender_t gender, bool isbeingemitted = false ) = 0;
virtual const char *GetWaveName( CUtlSymbol& sym ) = 0;
virtual CUtlSymbol AddWaveName( const char *name ) = 0;
virtual soundlevel_t LookupSoundLevel( const char *soundname ) = 0;
virtual const char *GetWavFileForSound( const char *soundname, char const *actormodel ) = 0;
virtual const char *GetWavFileForSound( const char *soundname, gender_t gender ) = 0;
virtual int CheckForMissingWavFiles( bool verbose ) = 0;
virtual const char *GetSourceFileForSound( int index ) const = 0;
// Iteration methods
virtual int First() const = 0;
virtual int Next( int i ) const = 0;
virtual int InvalidIndex() const = 0;
virtual CSoundParametersInternal *InternalGetParametersForSound( int index ) = 0;
// The host application is responsible for dealing with dirty sound scripts, etc.
virtual bool AddSound( const char *soundname, const char *scriptfile, const CSoundParametersInternal& params ) = 0;
virtual void RemoveSound( const char *soundname ) = 0;
virtual void MoveSound( const char *soundname, const char *newscript ) = 0;
virtual void RenameSound( const char *soundname, const char *newname ) = 0;
virtual void UpdateSoundParameters( const char *soundname, const CSoundParametersInternal& params ) = 0;
virtual int GetNumSoundScripts() const = 0;
virtual char const *GetSoundScriptName( int index ) const = 0;
virtual bool IsSoundScriptDirty( int index ) const = 0;
virtual int FindSoundScript( const char *name ) const = 0;
virtual void SaveChangesToSoundScript( int scriptindex ) = 0;
virtual void ExpandSoundNameMacros( CSoundParametersInternal& params, char const *wavename ) = 0;
virtual gender_t GetActorGender( char const *actormodel ) = 0;
virtual void GenderExpandString( char const *actormodel, char const *in, char *out, int maxlen ) = 0;
virtual void GenderExpandString( gender_t gender, char const *in, char *out, int maxlen ) = 0;
virtual bool IsUsingGenderToken( char const *soundname ) = 0;
// For blowing away caches based on filetimstamps of the manifest, or of any of the
// .txt files that are read into the sound emitter system
virtual unsigned int GetManifestFileTimeChecksum() = 0;
// Called from both client and server (single player) or just one (server only in dedicated server and client only if connected to a remote server)
// Called by LevelInitPreEntity to override sound scripts for the mod with level specific overrides based on custom mapnames, etc.
virtual void AddSoundOverrides( char const *scriptfile, bool bPreload = false ) = 0;
// Called by either client or server in LevelShutdown to clear out custom overrides
virtual void ClearSoundOverrides() = 0;
virtual bool GetParametersForSoundEx( const char *soundname, HSOUNDSCRIPTHANDLE& handle, CSoundParameters& params, gender_t gender, bool isbeingemitted = false ) = 0;
virtual soundlevel_t LookupSoundLevelByHandle( char const *soundname, HSOUNDSCRIPTHANDLE& handle ) = 0;
virtual void ReloadSoundEntriesInList( IFileList *pFilesToReload ) = 0;
};
#endif // ISOUNDEMITTERSYSTEMBASE_H

View File

@ -0,0 +1,583 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "cbase.h"
#if !defined(_STATIC_LINKED) || defined(SOUNDEMITTERSYSTEM_DLL)
#include "SoundEmitterSystem/isoundemittersystembase.h"
#include "interval.h"
#include "soundchars.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
struct SoundChannels
{
int channel;
const char *name;
};
// NOTE: This will need to be updated if channel names are added/removed
static SoundChannels g_pChannelNames[] =
{
{ CHAN_AUTO, "CHAN_AUTO" },
{ CHAN_WEAPON, "CHAN_WEAPON" },
{ CHAN_VOICE, "CHAN_VOICE" },
{ CHAN_ITEM, "CHAN_ITEM" },
{ CHAN_BODY, "CHAN_BODY" },
{ CHAN_STREAM, "CHAN_STREAM" },
{ CHAN_STATIC, "CHAN_STATIC" },
{ CHAN_VOICE2, "CHAN_VOICE2" },
};
struct VolumeLevel
{
float volume;
const char *name;
};
static VolumeLevel g_pVolumeLevels[] =
{
{ VOL_NORM, "VOL_NORM" },
};
struct PitchLookup
{
float pitch;
const char *name;
};
static PitchLookup g_pPitchLookup[] =
{
{ PITCH_NORM, "PITCH_NORM" },
{ PITCH_LOW, "PITCH_LOW" },
{ PITCH_HIGH, "PITCH_HIGH" },
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
struct SoundLevelLookup
{
soundlevel_t level;
char const *name;
};
// NOTE: Needs to reflect the soundlevel_t enum defined in soundflags.h
static SoundLevelLookup g_pSoundLevels[] =
{
{ SNDLVL_NONE, "SNDLVL_NONE" },
{ SNDLVL_20dB, "SNDLVL_20dB" },
{ SNDLVL_25dB, "SNDLVL_25dB" },
{ SNDLVL_30dB, "SNDLVL_30dB" },
{ SNDLVL_35dB, "SNDLVL_35dB" },
{ SNDLVL_40dB, "SNDLVL_40dB" },
{ SNDLVL_45dB, "SNDLVL_45dB" },
{ SNDLVL_50dB, "SNDLVL_50dB" },
{ SNDLVL_55dB, "SNDLVL_55dB" },
{ SNDLVL_IDLE, "SNDLVL_IDLE" },
{ SNDLVL_TALKING, "SNDLVL_TALKING" },
{ SNDLVL_60dB, "SNDLVL_60dB" },
{ SNDLVL_65dB, "SNDLVL_65dB" },
{ SNDLVL_STATIC, "SNDLVL_STATIC" },
{ SNDLVL_70dB, "SNDLVL_70dB" },
{ SNDLVL_NORM, "SNDLVL_NORM" },
{ SNDLVL_75dB, "SNDLVL_75dB" },
{ SNDLVL_80dB, "SNDLVL_80dB" },
{ SNDLVL_85dB, "SNDLVL_85dB" },
{ SNDLVL_90dB, "SNDLVL_90dB" },
{ SNDLVL_95dB, "SNDLVL_95dB" },
{ SNDLVL_100dB, "SNDLVL_100dB" },
{ SNDLVL_105dB, "SNDLVL_105dB" },
{ SNDLVL_110dB, "SNDLVL_110dB" },
{ SNDLVL_120dB, "SNDLVL_120dB" },
{ SNDLVL_130dB, "SNDLVL_130dB" },
{ SNDLVL_GUNFIRE, "SNDLVL_GUNFIRE" },
{ SNDLVL_140dB, "SNDLVL_140dB" },
{ SNDLVL_150dB, "SNDLVL_150dB" },
{ SNDLVL_180dB, "SNDLVL_180dB" },
};
static const char *_SoundLevelToString( soundlevel_t level )
{
int c = ARRAYSIZE( g_pSoundLevels );
int i;
for ( i = 0 ; i < c; i++ )
{
SoundLevelLookup *entry = &g_pSoundLevels[ i ];
if ( entry->level == level )
return entry->name;
}
static char sz[ 32 ];
Q_snprintf( sz, sizeof( sz ), "%i", (int)level );
return sz;
}
static const char *_ChannelToString( int channel )
{
int c = ARRAYSIZE( g_pChannelNames );
int i;
for ( i = 0 ; i < c; i++ )
{
SoundChannels *entry = &g_pChannelNames[ i ];
if ( entry->channel == channel )
return entry->name;
}
static char sz[ 32 ];
Q_snprintf( sz, sizeof( sz ), "%i", (int)channel );
return sz;
}
static const char *_VolumeToString( float volume )
{
int c = ARRAYSIZE( g_pVolumeLevels );
int i;
for ( i = 0 ; i < c; i++ )
{
VolumeLevel *entry = &g_pVolumeLevels[ i ];
if ( entry->volume == volume )
return entry->name;
}
static char sz[ 32 ];
Q_snprintf( sz, sizeof( sz ), "%.3f", volume );
return sz;
}
static const char *_PitchToString( float pitch )
{
int c = ARRAYSIZE( g_pPitchLookup );
int i;
for ( i = 0 ; i < c; i++ )
{
PitchLookup *entry = &g_pPitchLookup[ i ];
if ( entry->pitch == pitch )
return entry->name;
}
static char sz[ 32 ];
Q_snprintf( sz, sizeof( sz ), "%.3f", pitch );
return sz;
}
#define SNDLVL_PREFIX "SNDLVL_"
soundlevel_t TextToSoundLevel( const char *key )
{
if ( !key )
{
Assert( 0 );
return SNDLVL_NORM;
}
int c = ARRAYSIZE( g_pSoundLevels );
int i;
for ( i = 0 ; i < c; i++ )
{
SoundLevelLookup *entry = &g_pSoundLevels[ i ];
if ( !Q_strcasecmp( key, entry->name ) )
return entry->level;
}
if ( !Q_strnicmp( key, SNDLVL_PREFIX, Q_strlen( SNDLVL_PREFIX ) ) )
{
char const *val = key + Q_strlen( SNDLVL_PREFIX );
int sndlvl = atoi( val );
if ( sndlvl > 0 && sndlvl <= 180 )
{
return ( soundlevel_t )sndlvl;
}
}
DevMsg( "CSoundEmitterSystem: Unknown sound level %s\n", key );
return SNDLVL_NORM;
}
//-----------------------------------------------------------------------------
// Purpose: Convert "chan_xxx" into integer value for channel
// Input : *name -
// Output : static int
//-----------------------------------------------------------------------------
int TextToChannel( const char *name )
{
if ( !name )
{
Assert( 0 );
// CHAN_AUTO
return CHAN_AUTO;
}
if ( Q_strncasecmp( name, "chan_", strlen( "chan_" ) ) )
{
return atoi( name );
}
int c = ARRAYSIZE( g_pChannelNames );
int i;
for ( i = 0; i < c; i++ )
{
if ( !Q_strcasecmp( name, g_pChannelNames[ i ].name ) )
{
return g_pChannelNames[ i ].channel;
}
}
// At this point, it starts with chan_ but is not recognized
// atoi would return 0, so just do chan auto
DevMsg( "CSoundEmitterSystem: Warning, unknown channel type in sounds.txt (%s)\n", name );
return CHAN_AUTO;
}
const char *SoundLevelToString( soundlevel_t level )
{
int c = ARRAYSIZE( g_pSoundLevels );
int i;
for ( i = 0 ; i < c; i++ )
{
SoundLevelLookup *entry = &g_pSoundLevels[ i ];
if ( entry->level == level )
return entry->name;
}
static char sz[ 32 ];
Q_snprintf( sz, sizeof( sz ), "%i", (int)level );
return sz;
}
const char *ChannelToString( int channel )
{
int c = ARRAYSIZE( g_pChannelNames );
int i;
for ( i = 0 ; i < c; i++ )
{
SoundChannels *entry = &g_pChannelNames[ i ];
if ( entry->channel == channel )
return entry->name;
}
static char sz[ 32 ];
Q_snprintf( sz, sizeof( sz ), "%i", (int)channel );
return sz;
}
const char *VolumeToString( float volume )
{
int c = ARRAYSIZE( g_pVolumeLevels );
int i;
for ( i = 0 ; i < c; i++ )
{
VolumeLevel *entry = &g_pVolumeLevels[ i ];
if ( entry->volume == volume )
return entry->name;
}
static char sz[ 32 ];
Q_snprintf( sz, sizeof( sz ), "%.3f", volume );
return sz;
}
const char *PitchToString( float pitch )
{
int c = ARRAYSIZE( g_pPitchLookup );
int i;
for ( i = 0 ; i < c; i++ )
{
PitchLookup *entry = &g_pPitchLookup[ i ];
if ( entry->pitch == pitch )
return entry->name;
}
static char sz[ 32 ];
Q_snprintf( sz, sizeof( sz ), "%.3f", pitch );
return sz;
}
CSoundParametersInternal::CSoundParametersInternal()
{
m_pConvertedNames = m_pSoundNames = NULL;
m_nConvertedNames = m_nSoundNames = 0;
channel = CHAN_AUTO; // 0
volume.start = VOL_NORM; // 1.0f
volume.range = 0.0f;
pitch.start = PITCH_NORM; // 100
pitch.range = 0;
soundlevel.start = SNDLVL_NORM; // 75dB
soundlevel.range = 0;
delay_msec = 0;
play_to_owner_only = false;
had_missing_wave_files = false;
uses_gender_token = false;
}
CSoundParametersInternal::CSoundParametersInternal( const CSoundParametersInternal& src )
{
m_pSoundNames = NULL;
m_pConvertedNames = NULL;
m_nSoundNames = 0;
m_nConvertedNames = 0;
CopyFrom( src );
}
CSoundParametersInternal::~CSoundParametersInternal()
{
if ( m_nSoundNames > 1 )
free(m_pSoundNames );
if ( m_nConvertedNames > 1 )
free( m_pConvertedNames);
m_pConvertedNames = NULL;
m_pSoundNames = NULL;
m_nSoundNames = 0;
m_nConvertedNames = 0;
}
void CSoundParametersInternal::CopyFrom( const CSoundParametersInternal& src )
{
if ( m_nSoundNames > 1 )
free(m_pSoundNames);
if ( m_nConvertedNames > 1 )
free(m_pConvertedNames);
channel = src.channel;
volume = src.volume;
pitch = src.pitch;
soundlevel = src.soundlevel;
delay_msec = src.delay_msec;
play_to_owner_only = src.play_to_owner_only;
m_nSoundNames = src.m_nSoundNames;
if ( m_nSoundNames )
{
if ( m_nSoundNames > 1 )
{
m_pSoundNames = (SoundFile*)malloc( sizeof(SoundFile)*m_nSoundNames);
memcpy( m_pSoundNames, src.m_pSoundNames, m_nSoundNames * sizeof(SoundFile) );
}
else
{
m_pSoundNames = src.m_pSoundNames;
}
}
else
{
m_pSoundNames = NULL;
}
m_nConvertedNames = src.m_nConvertedNames;
if ( m_nConvertedNames )
{
if ( m_nConvertedNames > 1 )
{
m_pConvertedNames = (SoundFile*)malloc( sizeof(SoundFile)*m_nConvertedNames);
memcpy( m_pConvertedNames, src.m_pConvertedNames, m_nConvertedNames * sizeof(SoundFile) );
}
else
{
m_pConvertedNames = src.m_pConvertedNames;
}
}
else
{
m_pConvertedNames = NULL;
}
had_missing_wave_files = src.had_missing_wave_files;
uses_gender_token = src.uses_gender_token;
}
#define CompareInterval( i1, i2 ) ( memcmp( &(i1), &(i2), sizeof(i1) ) == 0 )
bool CSoundParametersInternal::operator == ( const CSoundParametersInternal& other ) const
{
if ( this == &other )
return true;
if ( channel != other.channel )
return false;
if ( !CompareInterval( volume, other.volume ) )
return false;
if ( !CompareInterval( pitch, other.pitch ) )
return false;
if ( !CompareInterval( soundlevel, other.soundlevel ) )
return false;
if ( delay_msec != other.delay_msec )
return false;
if ( play_to_owner_only != other.play_to_owner_only )
return false;
if ( m_nSoundNames != other.m_nSoundNames )
return false;
// Compare items
int c = m_nSoundNames;
for ( int i = 0; i < c; i++ )
{
if ( GetSoundNames()[ i ].symbol != other.GetSoundNames()[ i ].symbol )
return false;
}
return true;
}
float16 ZERO_FLOAT16;
const char *CSoundParametersInternal::VolumeToString( void ) const
{
if ( volume.range == ZERO_FLOAT16 )
{
return _VolumeToString( volume.start );
}
static char sz[ 64 ];
Q_snprintf( sz, sizeof( sz ), "%.3f, %.3f", (float)volume.start, (float)volume.start + (float)volume.range );
return sz;
}
const char *CSoundParametersInternal::ChannelToString( void ) const
{
return _ChannelToString( channel );
}
const char *CSoundParametersInternal::SoundLevelToString( void ) const
{
if ( soundlevel.range == 0 )
{
return _SoundLevelToString( (soundlevel_t)(int)soundlevel.start );
}
static char sz[ 64 ];
Q_snprintf( sz, sizeof( sz ), "%i, %i", (soundlevel_t)(int)soundlevel.start, (soundlevel_t)(int)(soundlevel.start + soundlevel.range ) );
return sz;
}
const char *CSoundParametersInternal::PitchToString( void ) const
{
if ( pitch.range == 0 )
{
return _PitchToString( (int)pitch.start );
}
static char sz[ 64 ];
Q_snprintf( sz, sizeof( sz ), "%i, %i", (int)pitch.start, (int)(pitch.start + pitch.range ) );
return sz;
}
void CSoundParametersInternal::VolumeFromString( const char *sz )
{
if ( !Q_strcasecmp( sz, "VOL_NORM" ) )
{
volume.start = VOL_NORM;
volume.range = 0.0f;
}
else
{
volume.FromInterval( ReadInterval( sz ) );
}
}
void CSoundParametersInternal::ChannelFromString( const char *sz )
{
channel = TextToChannel( sz );
}
void CSoundParametersInternal::PitchFromString( const char *sz )
{
if ( !Q_strcasecmp( sz, "PITCH_NORM" ) )
{
pitch.start = PITCH_NORM;
pitch.range = 0;
}
else if ( !Q_strcasecmp( sz, "PITCH_LOW" ) )
{
pitch.start = PITCH_LOW;
pitch.range = 0;
}
else if ( !Q_strcasecmp( sz, "PITCH_HIGH" ) )
{
pitch.start = PITCH_HIGH;
pitch.range = 0;
}
else
{
pitch.FromInterval( ReadInterval( sz ) );
}
}
void CSoundParametersInternal::SoundLevelFromString( const char *sz )
{
if ( !Q_strncasecmp( sz, "SNDLVL_", strlen( "SNDLVL_" ) ) )
{
soundlevel.start = TextToSoundLevel( sz );
soundlevel.range = 0;
}
else
{
soundlevel.FromInterval( ReadInterval( sz ) );
}
}
void CSoundParametersInternal::AddToTail( SoundFile **pDest, uint16 *pDestCount, const SoundFile &source )
{
(*pDestCount)++;
if ( *pDestCount == 1 )
{
// NOTE: when there's only one soundfile in the list, we store it
// packed into the pointer itself, the four bytes for the pointer is just used to store the sound file!
COMPILE_TIME_ASSERT( sizeof(SoundFile) <= sizeof(SoundFile *) );
*((SoundFile *)(pDest)) = source;
}
else
{
SoundFile temp;
if ( *pDestCount == 2 )
{
// Copying from a list of one soundfile. Save off the struct
// packed into the pointer field.
temp = *((SoundFile *)(pDest));
*pDest = NULL;
}
*pDest = (SoundFile *)realloc( *pDest, (*pDestCount) * sizeof(SoundFile) );
(*pDest)[ *pDestCount - 1 ] = source;
if ( *pDestCount == 2 )
{
(*pDest)[0] = temp;
}
}
}
#endif // !_STATIC_LINKED || SOUNDEMITTERSYSTEM_DLL

View File

@ -0,0 +1,240 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include <stdlib.h>
#include <ctype.h>
#include "utlbuffer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: Advances until non-whitespace hit
//-----------------------------------------------------------------------------
ucs2 *AdvanceOverWhitespace(ucs2 *Start)
{
while (*Start != 0 && iswspace(*Start))
{
Start++;
}
return Start;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
ucs2 *ReadUnicodeToken(ucs2 *start, ucs2 *token, int tokenBufferSize, bool &quoted)
{
// skip over any whitespace
start = AdvanceOverWhitespace(start);
quoted = false;
*token = 0;
if (!*start)
{
return start;
}
// check to see if it's a quoted string
if (*start == '\"')
{
quoted = true;
// copy out the string until we hit an end quote
start++;
int count = 0;
while (*start && *start != '\"' && count < tokenBufferSize-1)
{
// check for special characters
if (*start == '\\' && *(start+1) == 'n')
{
start++;
*token = '\n';
}
else if (*start == '\\' && *(start+1) == '\"')
{
start++;
*token = '\"';
}
else
{
*token = *start;
}
start++;
token++;
count++;
}
if (*start == '\"')
{
start++;
}
}
else
{
// copy out the string until we hit a whitespace
int count = 0;
while (*start && !iswspace(*start) && count < tokenBufferSize-1)
{
// no checking for special characters if it's not a quoted string
*token = *start;
start++;
token++;
count++;
}
}
*token = 0;
return start;
}
//-----------------------------------------------------------------------------
// Purpose: Same as above but no translation of \n
//-----------------------------------------------------------------------------
ucs2 *ReadUnicodeTokenNoSpecial(ucs2 *start, ucs2 *token, int tokenBufferSize, bool &quoted)
{
// skip over any whitespace
start = AdvanceOverWhitespace(start);
quoted = false;
*token = 0;
if (!*start)
{
return start;
}
// check to see if it's a quoted string
if (*start == '\"')
{
quoted = true;
// copy out the string until we hit an end quote
start++;
int count = 0;
while (*start && *start != '\"' && count < tokenBufferSize-1)
{
// check for special characters
/*
if (*start == '\\' && *(start+1) == 'n')
{
start++;
*token = '\n';
}
else
*/
if (*start == '\\' && *(start+1) == '\"')
{
start++;
*token = '\"';
}
else
{
*token = *start;
}
start++;
token++;
count++;
}
if (*start == '\"')
{
start++;
}
}
else
{
// copy out the string until we hit a whitespace
int count = 0;
while (*start && !iswspace(*start) && count < tokenBufferSize-1)
{
// no checking for special characters if it's not a quoted string
*token = *start;
start++;
token++;
count++;
}
}
*token = 0;
return start;
}
//-----------------------------------------------------------------------------
// Purpose: Returns the first character after the next EOL characters
//-----------------------------------------------------------------------------
ucs2 *ReadToEndOfLine(ucs2 *start)
{
if (!*start)
return start;
while (*start)
{
if (*start == 0x0D || *start== 0x0A)
break;
start++;
}
while (*start == 0x0D || *start== 0x0A)
start++;
return start;
}
//-----------------------------------------------------------------------------
// Purpose: file writing
//-----------------------------------------------------------------------------
void WriteUnicodeString(CUtlBuffer &buf, const wchar_t *string, bool addQuotes)
{
if (addQuotes)
{
buf.PutUnsignedShort('\"');
}
for (const wchar_t *ws = string; *ws != 0; ws++)
{
// handle special characters
if (addQuotes && *ws == '\"')
{
buf.PutUnsignedShort('\\');
}
// write the character
buf.PutUnsignedShort(*ws);
}
if (addQuotes)
{
buf.PutUnsignedShort('\"');
}
}
//-----------------------------------------------------------------------------
// Purpose: file writing
//-----------------------------------------------------------------------------
void WriteAsciiStringAsUnicode(CUtlBuffer &buf, const char *string, bool addQuotes)
{
if (addQuotes)
{
buf.PutUnsignedShort('\"');
}
for (const char *sz = string; *sz != 0; sz++)
{
// handle special characters
if (addQuotes && *sz == '\"')
{
buf.PutUnsignedShort('\\');
}
buf.PutUnsignedShort(*sz);
}
if (addQuotes)
{
buf.PutUnsignedShort('\"');
}
}

View File

@ -0,0 +1,28 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef UNICODEFILEHELPERS_H
#define UNICODEFILEHELPERS_H
#ifdef _WIN32
#pragma once
#endif
#include <stdlib.h>
// helper functions for parsing unicode file buffers
ucs2 *AdvanceOverWhitespace(ucs2 *start);
ucs2 *ReadUnicodeToken(ucs2 *start, ucs2 *token, int tokenBufferSize, bool &quoted);
ucs2 *ReadUnicodeTokenNoSpecial(ucs2 *start, ucs2 *token, int tokenBufferSize, bool &quoted);
ucs2 *ReadToEndOfLine(ucs2 *start);
// writing to unicode files via CUtlBuffer
class CUtlBuffer;
void WriteUnicodeString(CUtlBuffer &buffer, const wchar_t *string, bool addQuotes = false);
void WriteAsciiStringAsUnicode(CUtlBuffer &buffer, const char *string, bool addQuotes = false);
#endif // UNICODEFILEHELPERS_H

1001
public/UtlCachedFileData.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,112 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: An extra interface implemented by the material system
// implementation of vgui::ISurface
//
// $Revision: $
// $NoKeywords: $
//===========================================================================//
#ifndef IMATSYSTEMSURFACE_H
#define IMATSYSTEMSURFACE_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui/VGUI.h>
#include "vgui/ISurface.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class VMatrix;
class IMaterial;
struct InputEvent_t;
//-----------------------------------------------------------------------------
// Callbacks for mouse getting + setting
//-----------------------------------------------------------------------------
typedef void (*GetMouseCallback_t)(int &x, int &y);
typedef void (*SetMouseCallback_t)(int x, int y);
//-----------------------------------------------------------------------------
// Callbacks for sound playing
//-----------------------------------------------------------------------------
typedef void (*PlaySoundFunc_t)(const char *pFileName);
//-----------------------------------------------------------------------------
//
// An extra interface implemented by the material system implementation of vgui::ISurface
//
//-----------------------------------------------------------------------------
#define MAT_SYSTEM_SURFACE_INTERFACE_VERSION "MatSystemSurface008"
class IMatSystemSurface : public vgui::ISurface
{
public:
// Hook needed to get input to work.
// If the app drives the input (like the engine needs to do for VCR mode),
// it can set bLetAppDriveInput to true and call HandleInputEvent for the input events.
virtual void AttachToWindow( void *hwnd, bool bLetAppDriveInput=false ) = 0;
// Tells the surface to ignore windows messages
virtual void EnableWindowsMessages( bool bEnable ) = 0;
// Starts, ends 3D painting
// NOTE: These methods should only be called from within the paint()
// method of a panel.
virtual void Begin3DPaint( int iLeft, int iTop, int iRight, int iBottom, bool bRenderToTexture = true ) = 0;
virtual void End3DPaint() = 0;
// NOTE: This also should only be called from within the paint()
// method of a panel. Use it to disable clipping for the rendering
// of this panel.
virtual void DisableClipping( bool bDisable ) = 0;
virtual void GetClippingRect( int &left, int &top, int &right, int &bottom, bool &bClippingDisabled ) = 0; // <<<<< NOTE: output flag is *disabled* state, not enabled, to match the rest of the interface
virtual void SetClippingRect( int left, int top, int right, int bottom ) = 0;
// Prevents vgui from changing the cursor
virtual bool IsCursorLocked() const = 0;
// Sets the mouse get + set callbacks
virtual void SetMouseCallbacks( GetMouseCallback_t getFunc, SetMouseCallback_t setFunc ) = 0;
// Installs a function to play sounds
virtual void InstallPlaySoundFunc( PlaySoundFunc_t soundFunc ) = 0;
// Some drawing methods that cannot be accomplished under Win32
virtual void DrawColoredCircle( int centerx, int centery, float radius, int r, int g, int b, int a ) = 0;
virtual int DrawColoredText( vgui::HFont font, int x, int y, int r, int g, int b, int a, PRINTF_FORMAT_STRING const char *fmt, ... ) = 0;
// Draws text with current font at position and wordwrapped to the rect using color values specified
virtual void DrawColoredTextRect( vgui::HFont font, int x, int y, int w, int h, int r, int g, int b, int a, PRINTF_FORMAT_STRING const char *fmt, ... ) = 0;
virtual void DrawTextHeight( vgui::HFont font, int w, int& h, PRINTF_FORMAT_STRING const char *fmt, ... ) = 0;
// Returns the length of the text string in pixels
virtual int DrawTextLen( vgui::HFont font, PRINTF_FORMAT_STRING const char *fmt, ... ) = 0;
// Draws a panel in 3D space. Assumes view + projection are already set up
// Also assumes the (x,y) coordinates of the panels are defined in 640xN coords
// (N isn't necessary 480 because the panel may not be 4x3)
// The width + height specified are the size of the panel in world coordinates
virtual void DrawPanelIn3DSpace( vgui::VPANEL pRootPanel, const VMatrix &panelCenterToWorld, int nPixelWidth, int nPixelHeight, float flWorldWidth, float flWorldHeight ) = 0;
// Binds a material to a surface texture ID
virtual void DrawSetTextureMaterial( int id, IMaterial *pMaterial ) = 0;
// Handles an input event, returns true if the event should be filtered from the rest of the game
virtual bool HandleInputEvent( const InputEvent_t &event ) = 0;
virtual void Set3DPaintTempRenderTarget( const char *pRenderTargetName ) = 0;
virtual void Reset3DPaintTempRenderTarget( void ) = 0;
// Gets a material bound to a surface texture ID
virtual IMaterial *DrawGetTextureMaterial( int id ) = 0;
};
#endif // IMATSYSTEMSURFACE_H

View File

@ -0,0 +1,88 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef IMATSYSTEMSURFACEV5_H
#define IMATSYSTEMSURFACEV5_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui/VGUI.h>
#include "vgui/isurfacev30.h"
namespace MatSystemSurfaceV5
{
#define MAT_SYSTEM_SURFACE_INTERFACE_VERSION_5 "MatSystemSurface005"
class IMatSystemSurface : public SurfaceV30::ISurface
{
public:
// Hook needed to get input to work.
// If the app drives the input (like the engine needs to do for VCR mode),
// it can set bLetAppDriveInput to true and call HandleWindowMessage for the Windows messages.
virtual void AttachToWindow( void *hwnd, bool bLetAppDriveInput=false ) = 0;
// If you specified true for bLetAppDriveInput, then call this for each window message that comes in.
virtual void HandleWindowMessage( void *hwnd, unsigned int uMsg, unsigned int wParam, long lParam ) = 0;
// Tells the surface to ignore windows messages
virtual void EnableWindowsMessages( bool bEnable ) = 0;
// Starts, ends 3D painting
// NOTE: These methods should only be called from within the paint()
// method of a panel.
virtual void Begin3DPaint( int iLeft, int iTop, int iRight, int iBottom ) = 0;
virtual void End3DPaint() = 0;
// NOTE: This also should only be called from within the paint()
// method of a panel. Use it to disable clipping for the rendering
// of this panel.
virtual void DisableClipping( bool bDisable ) = 0;
// Prevents vgui from changing the cursor
virtual bool IsCursorLocked() const = 0;
// Sets the mouse get + set callbacks
virtual void SetMouseCallbacks( GetMouseCallback_t getFunc, SetMouseCallback_t setFunc ) = 0;
// Installs a function to play sounds
virtual void InstallPlaySoundFunc( PlaySoundFunc_t soundFunc ) = 0;
// Some drawing methods that cannot be accomplished under Win32
virtual void DrawColoredCircle( int centerx, int centery, float radius, int r, int g, int b, int a ) = 0;
virtual int DrawColoredText( vgui::HFont font, int x, int y, int r, int g, int b, int a, PRINTF_FORMAT_STRING char *fmt, ... ) = 0;
// Draws text with current font at position and wordwrapped to the rect using color values specified
virtual void DrawColoredTextRect( vgui::HFont font, int x, int y, int w, int h, int r, int g, int b, int a, PRINTF_FORMAT_STRING char *fmt, ... ) = 0;
virtual void DrawTextHeight( vgui::HFont font, int w, int& h, PRINTF_FORMAT_STRING char *fmt, ... ) = 0;
// Returns the length of the text string in pixels
virtual int DrawTextLen( vgui::HFont font, PRINTF_FORMAT_STRING char *fmt, ... ) = 0;
// Draws a panel in 3D space. Assumes view + projection are already set up
// Also assumes the (x,y) coordinates of the panels are defined in 640xN coords
// (N isn't necessary 480 because the panel may not be 4x3)
// The width + height specified are the size of the panel in world coordinates
virtual void DrawPanelIn3DSpace( vgui::VPANEL pRootPanel, const VMatrix &panelCenterToWorld, int nPixelWidth, int nPixelHeight, float flWorldWidth, float flWorldHeight ) = 0;
// Binds a material to a surface texture ID
virtual void DrawSetTextureMaterial( int id, IMaterial *pMaterial ) = 0;
};
}
//-----------------------------------------------------------------------------
// FIXME: This works around using scoped interfaces w/ EXPOSE_SINGLE_INTERFACE
//-----------------------------------------------------------------------------
class IMatSystemSurfaceV5 : public MatSystemSurfaceV5::IMatSystemSurface
{
public:
};
#endif // IMATSYSTEMSURFACEV5_H

4487
public/XUnzip.cpp Normal file

File diff suppressed because it is too large Load Diff

3033
public/XZip.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,158 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: An application framework
//
// $Revision: $
// $NoKeywords: $
//===========================================================================//
#ifndef APPFRAMEWORK_H
#define APPFRAMEWORK_H
#ifdef _WIN32
#pragma once
#endif
#include "appframework/IAppSystemGroup.h"
//-----------------------------------------------------------------------------
// Gets the application instance..
//-----------------------------------------------------------------------------
void *GetAppInstance();
//-----------------------------------------------------------------------------
// Sets the application instance, should only be used if you're not calling AppMain.
//-----------------------------------------------------------------------------
void SetAppInstance( void* hInstance );
//-----------------------------------------------------------------------------
// Main entry point for the application
//-----------------------------------------------------------------------------
int AppMain( void* hInstance, void* hPrevInstance, const char* lpCmdLine, int nCmdShow, CAppSystemGroup *pAppSystemGroup );
int AppMain( int argc, char **argv, CAppSystemGroup *pAppSystemGroup );
//-----------------------------------------------------------------------------
// Used to startup/shutdown the application
//-----------------------------------------------------------------------------
int AppStartup( void* hInstance, void* hPrevInstance, const char* lpCmdLine, int nCmdShow, CAppSystemGroup *pAppSystemGroup );
int AppStartup( int argc, char **argv, CAppSystemGroup *pAppSystemGroup );
void AppShutdown( CAppSystemGroup *pAppSystemGroup );
//-----------------------------------------------------------------------------
// Macros to create singleton application objects for windowed + console apps
//-----------------------------------------------------------------------------
#if !defined( _X360 )
#ifdef WIN32
#define DEFINE_WINDOWED_APPLICATION_OBJECT_GLOBALVAR( _globalVarName ) \
int __stdcall WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) \
{ \
return AppMain( hInstance, hPrevInstance, lpCmdLine, nCmdShow, &_globalVarName ); \
}
#elif defined( OSX )
#define DEFINE_WINDOWED_APPLICATION_OBJECT_GLOBALVAR( _globalVarName ) \
int main( int argc, char **argv ) \
{ \
extern int ValveCocoaMain( int argc, char **argv, CAppSystemGroup *pAppSystemGroup ); \
return ValveCocoaMain( argc, argv, &_globalVarName ); \
}
#elif defined( LINUX )
#define DEFINE_WINDOWED_APPLICATION_OBJECT_GLOBALVAR( _globalVarName ) \
int main( int argc, char **argv ) \
{ \
extern int ValveLinuxWindowedMain( int argc, char **argv, CAppSystemGroup *pAppSystemGroup ); \
return ValveLinuxWindowedMain( argc, argv, &_globalVarName ); \
}
#else
#error
#endif
#else
#define DEFINE_WINDOWED_APPLICATION_OBJECT_GLOBALVAR( _globalVarName ) \
void __cdecl main() \
{ \
AppMain( (HINSTANCE)1, (HINSTANCE)0, NULL, 0, &_globalVarName ); \
}
#endif
#if !defined( _X360 )
#define DEFINE_CONSOLE_APPLICATION_OBJECT_GLOBALVAR( _globalVarName ) \
int main( int argc, char **argv ) \
{ \
return AppMain( argc, argv, &_globalVarName ); \
}
#else
#define DEFINE_CONSOLE_APPLICATION_OBJECT_GLOBALVAR( _globalVarName ) \
void __cdecl main() \
{ \
AppMain( 0, (char**)NULL, &_globalVarName ); \
}
#endif
#define DEFINE_WINDOWED_APPLICATION_OBJECT( _className ) \
static _className __s_ApplicationObject; \
DEFINE_WINDOWED_APPLICATION_OBJECT_GLOBALVAR( __s_ApplicationObject )
#define DEFINE_CONSOLE_APPLICATION_OBJECT( _className ) \
static _className __s_ApplicationObject; \
DEFINE_CONSOLE_APPLICATION_OBJECT_GLOBALVAR( __s_ApplicationObject )
//-----------------------------------------------------------------------------
// This class is a helper class used for steam-based applications.
// It loads up the file system in preparation for using it to load other
// required modules from steam.
//-----------------------------------------------------------------------------
class CSteamApplication : public CAppSystemGroup
{
typedef CAppSystemGroup BaseClass;
public:
CSteamApplication( CSteamAppSystemGroup *pAppSystemGroup );
// Implementation of IAppSystemGroup
virtual bool Create( );
virtual bool PreInit( );
virtual int Main( );
virtual void PostShutdown();
virtual void Destroy();
// Use this version in cases where you can't control the main loop and
// expect to be ticked
virtual int Startup();
virtual void Shutdown();
protected:
IFileSystem *m_pFileSystem;
CSteamAppSystemGroup *m_pChildAppSystemGroup;
bool m_bSteam;
};
//-----------------------------------------------------------------------------
// Macros to help create singleton application objects for windowed + console steam apps
//-----------------------------------------------------------------------------
#define DEFINE_WINDOWED_STEAM_APPLICATION_OBJECT_GLOBALVAR( _className, _varName ) \
static CSteamApplication __s_SteamApplicationObject( &_varName ); \
DEFINE_WINDOWED_APPLICATION_OBJECT_GLOBALVAR( __s_SteamApplicationObject )
#define DEFINE_WINDOWED_STEAM_APPLICATION_OBJECT( _className ) \
static _className __s_ApplicationObject; \
static CSteamApplication __s_SteamApplicationObject( &__s_ApplicationObject ); \
DEFINE_WINDOWED_APPLICATION_OBJECT_GLOBALVAR( __s_SteamApplicationObject )
#define DEFINE_CONSOLE_STEAM_APPLICATION_OBJECT_GLOBALVAR( _className, _varName ) \
static CSteamApplication __s_SteamApplicationObject( &_varName ); \
DEFINE_CONSOLE_APPLICATION_OBJECT_GLOBALVAR( __s_SteamApplicationObject )
#define DEFINE_CONSOLE_STEAM_APPLICATION_OBJECT( _className ) \
static _className __s_ApplicationObject; \
static CSteamApplication __s_SteamApplicationObject( &__s_ApplicationObject ); \
DEFINE_CONSOLE_APPLICATION_OBJECT_GLOBALVAR( __s_SteamApplicationObject )
#endif // APPFRAMEWORK_H

View File

@ -0,0 +1,122 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: An application framework
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#ifndef IAPPSYSTEM_H
#define IAPPSYSTEM_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/interface.h"
//-----------------------------------------------------------------------------
// Client systems are singleton objects in the client codebase responsible for
// various tasks
// The order in which the client systems appear in this list are the
// order in which they are initialized and updated. They are shut down in
// reverse order from which they are initialized.
//-----------------------------------------------------------------------------
enum InitReturnVal_t
{
INIT_FAILED = 0,
INIT_OK,
INIT_LAST_VAL,
};
abstract_class IAppSystem
{
public:
// Here's where the app systems get to learn about each other
virtual bool Connect( CreateInterfaceFn factory ) = 0;
virtual void Disconnect() = 0;
// Here's where systems can access other interfaces implemented by this object
// Returns NULL if it doesn't implement the requested interface
virtual void *QueryInterface( const char *pInterfaceName ) = 0;
// Init, shutdown
virtual InitReturnVal_t Init() = 0;
virtual void Shutdown() = 0;
};
//-----------------------------------------------------------------------------
// Helper empty implementation of an IAppSystem
//-----------------------------------------------------------------------------
template< class IInterface >
class CBaseAppSystem : public IInterface
{
public:
// Here's where the app systems get to learn about each other
virtual bool Connect( CreateInterfaceFn factory ) { return true; }
virtual void Disconnect() {}
// Here's where systems can access other interfaces implemented by this object
// Returns NULL if it doesn't implement the requested interface
virtual void *QueryInterface( const char *pInterfaceName ) { return NULL; }
// Init, shutdown
virtual InitReturnVal_t Init() { return INIT_OK; }
virtual void Shutdown() {}
};
//-----------------------------------------------------------------------------
// Helper implementation of an IAppSystem for tier0
//-----------------------------------------------------------------------------
template< class IInterface >
class CTier0AppSystem : public CBaseAppSystem< IInterface >
{
public:
CTier0AppSystem( bool bIsPrimaryAppSystem = true )
{
m_bIsPrimaryAppSystem = bIsPrimaryAppSystem;
}
protected:
// NOTE: a single DLL may have multiple AppSystems it's trying to
// expose. If this is true, you must return true from only
// one of those AppSystems; not doing so will cause all static
// libraries connected to it to connect/disconnect multiple times
// NOTE: We don't do this as a virtual function to avoid
// having to up the version on all interfaces
bool IsPrimaryAppSystem() { return m_bIsPrimaryAppSystem; }
private:
bool m_bIsPrimaryAppSystem;
};
//-----------------------------------------------------------------------------
// This is the version of IAppSystem shipped 10/15/04
// NOTE: Never change this!!!
//-----------------------------------------------------------------------------
abstract_class IAppSystemV0
{
public:
// Here's where the app systems get to learn about each other
virtual bool Connect( CreateInterfaceFn factory ) = 0;
virtual void Disconnect() = 0;
// Here's where systems can access other interfaces implemented by this object
// Returns NULL if it doesn't implement the requested interface
virtual void *QueryInterface( const char *pInterfaceName ) = 0;
// Init, shutdown
virtual InitReturnVal_t Init() = 0;
virtual void Shutdown() = 0;
};
#endif // IAPPSYSTEM_H

View File

@ -0,0 +1,265 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: Defines a group of app systems that all have the same lifetime
// that need to be connected/initialized, etc. in a well-defined order
//
// $Revision: $
// $NoKeywords: $
//=============================================================================
#ifndef IAPPSYSTEMGROUP_H
#define IAPPSYSTEMGROUP_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/interface.h"
#include "tier1/utlvector.h"
#include "tier1/utldict.h"
#include "IAppSystem.h"
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
class IAppSystem;
class CSysModule;
class IBaseInterface;
class IFileSystem;
//-----------------------------------------------------------------------------
// Handle to a DLL
//-----------------------------------------------------------------------------
typedef int AppModule_t;
enum
{
APP_MODULE_INVALID = (AppModule_t)~0
};
//-----------------------------------------------------------------------------
// NOTE: The following methods must be implemented in your application
// although they can be empty implementations if you like...
//-----------------------------------------------------------------------------
abstract_class IAppSystemGroup
{
public:
// An installed application creation function, you should tell the group
// the DLLs and the singleton interfaces you want to instantiate.
// Return false if there's any problems and the app will abort
virtual bool Create( ) = 0;
// Allow the application to do some work after AppSystems are connected but
// they are all Initialized.
// Return false if there's any problems and the app will abort
virtual bool PreInit() = 0;
// Main loop implemented by the application
virtual int Main( ) = 0;
// Allow the application to do some work after all AppSystems are shut down
virtual void PostShutdown() = 0;
// Call an installed application destroy function, occurring after all modules
// are unloaded
virtual void Destroy() = 0;
};
//-----------------------------------------------------------------------------
// Specifies a module + interface name for initialization
//-----------------------------------------------------------------------------
struct AppSystemInfo_t
{
const char *m_pModuleName;
const char *m_pInterfaceName;
};
//-----------------------------------------------------------------------------
// This class represents a group of app systems that all have the same lifetime
// that need to be connected/initialized, etc. in a well-defined order
//-----------------------------------------------------------------------------
class CAppSystemGroup : public IAppSystemGroup
{
public:
// Used to determine where we exited out from the system
enum AppSystemGroupStage_t
{
CREATION = 0,
CONNECTION,
PREINITIALIZATION,
INITIALIZATION,
SHUTDOWN,
POSTSHUTDOWN,
DISCONNECTION,
DESTRUCTION,
NONE, // This means no error
};
public:
// constructor
CAppSystemGroup( CAppSystemGroup *pParentAppSystem = NULL );
// Runs the app system group.
// First, modules are loaded, next they are connected, followed by initialization
// Then Main() is run
// Then modules are shut down, disconnected, and unloaded
int Run( );
// Use this version in cases where you can't control the main loop and
// expect to be ticked
virtual int Startup();
virtual void Shutdown();
// Returns the stage at which the app system group ran into an error
AppSystemGroupStage_t GetErrorStage() const;
protected:
// These methods are meant to be called by derived classes of CAppSystemGroup
// Methods to load + unload DLLs
AppModule_t LoadModule( const char *pDLLName );
AppModule_t LoadModule( CreateInterfaceFn factory );
// Method to add various global singleton systems
IAppSystem *AddSystem( AppModule_t module, const char *pInterfaceName );
void AddSystem( IAppSystem *pAppSystem, const char *pInterfaceName );
// Simpler method of doing the LoadModule/AddSystem thing.
// Make sure the last AppSystemInfo has a NULL module name
bool AddSystems( AppSystemInfo_t *pSystems );
// Method to look up a particular named system...
void *FindSystem( const char *pInterfaceName );
// Gets at a class factory for the topmost appsystem group in an appsystem stack
static CreateInterfaceFn GetFactory();
private:
int OnStartup();
void OnShutdown();
void UnloadAllModules( );
void RemoveAllSystems();
// Method to connect/disconnect all systems
bool ConnectSystems( );
void DisconnectSystems();
// Method to initialize/shutdown all systems
InitReturnVal_t InitSystems();
void ShutdownSystems();
// Gets at the parent appsystem group
CAppSystemGroup *GetParent();
// Loads a module the standard way
virtual CSysModule *LoadModuleDLL( const char *pDLLName );
void ReportStartupFailure( int nErrorStage, int nSysIndex );
struct Module_t
{
CSysModule *m_pModule;
CreateInterfaceFn m_Factory;
char *m_pModuleName;
};
CUtlVector<Module_t> m_Modules;
CUtlVector<IAppSystem*> m_Systems;
CUtlDict<int, unsigned short> m_SystemDict;
CAppSystemGroup *m_pParentAppSystem;
AppSystemGroupStage_t m_nErrorStage;
friend void *AppSystemCreateInterfaceFn(const char *pName, int *pReturnCode);
friend class CSteamAppSystemGroup;
};
//-----------------------------------------------------------------------------
// This class represents a group of app systems that are loaded through steam
//-----------------------------------------------------------------------------
class CSteamAppSystemGroup : public CAppSystemGroup
{
public:
CSteamAppSystemGroup( IFileSystem *pFileSystem = NULL, CAppSystemGroup *pParentAppSystem = NULL );
// Used by CSteamApplication to set up necessary pointers if we can't do it in the constructor
void Setup( IFileSystem *pFileSystem, CAppSystemGroup *pParentAppSystem );
protected:
// Sets up the search paths
bool SetupSearchPaths( const char *pStartingDir, bool bOnlyUseStartingDir, bool bIsTool );
// Returns the game info path. Only works if you've called SetupSearchPaths first
const char *GetGameInfoPath() const;
private:
virtual CSysModule *LoadModuleDLL( const char *pDLLName );
IFileSystem *m_pFileSystem;
char m_pGameInfoPath[ MAX_PATH ];
};
//-----------------------------------------------------------------------------
// Helper empty decorator implementation of an IAppSystemGroup
//-----------------------------------------------------------------------------
template< class CBaseClass >
class CDefaultAppSystemGroup : public CBaseClass
{
public:
virtual bool Create( ) { return true; }
virtual bool PreInit() { return true; }
virtual void PostShutdown() {}
virtual void Destroy() {}
};
//-----------------------------------------------------------------------------
// Special helper for game info directory suggestion
//-----------------------------------------------------------------------------
class CFSSteamSetupInfo; // Forward declaration
//
// SuggestGameInfoDirFn_t
// Game info suggestion function.
// Provided by the application to possibly detect the suggested game info
// directory and initialize all the game-info-related systems appropriately.
// Parameters:
// pFsSteamSetupInfo steam file system setup information if available.
// pchPathBuffer buffer to hold game info directory path on return.
// nBufferLength length of the provided buffer to hold game info directory path.
// pbBubbleDirectories should contain "true" on return to bubble the directories up searching for game info file.
// Return values:
// Returns "true" if the game info directory path suggestion is available and
// was successfully copied into the provided buffer.
// Returns "false" otherwise, interpreted that no suggestion will be used.
//
typedef bool ( * SuggestGameInfoDirFn_t ) ( CFSSteamSetupInfo const *pFsSteamSetupInfo, char *pchPathBuffer, int nBufferLength, bool *pbBubbleDirectories );
//
// SetSuggestGameInfoDirFn
// Installs the supplied game info directory suggestion function.
// Parameters:
// pfnNewFn the new game info directory suggestion function.
// Returns:
// The previously installed suggestion function or NULL if none was installed before.
// This function never fails.
//
SuggestGameInfoDirFn_t SetSuggestGameInfoDirFn( SuggestGameInfoDirFn_t pfnNewFn );
#endif // APPSYSTEMGROUP_H

View File

@ -0,0 +1,71 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// Material editor
//=============================================================================
#ifndef VGUIMATSYSAPP_H
#define VGUIMATSYSAPP_H
#ifdef _WIN32
#pragma once
#endif
#include "appframework/tier3app.h"
//-----------------------------------------------------------------------------
// The application object
//-----------------------------------------------------------------------------
class CVguiMatSysApp : public CVguiSteamApp
{
typedef CVguiSteamApp BaseClass;
public:
CVguiMatSysApp();
// Methods of IApplication
virtual bool Create();
virtual bool PreInit();
virtual void PostShutdown();
virtual void Destroy();
// Returns the window handle (HWND in Win32)
void* GetAppWindow();
// Gets the window size
int GetWindowWidth() const;
int GetWindowHeight() const;
protected:
void AppPumpMessages();
// Sets the video mode
bool SetVideoMode( );
// Sets up the game path
bool SetupSearchPaths( const char *pStartingDir, bool bOnlyUseStartingDir, bool bIsTool );
private:
// Returns the app name
virtual const char *GetAppName() = 0;
virtual bool AppUsesReadPixels() { return false; }
// Creates the app window
virtual void *CreateAppWindow( char const *pTitle, bool bWindowed, int w, int h );
void *m_HWnd;
int m_nWidth;
int m_nHeight;
};
#endif // VGUIMATSYSAPP_H

View File

@ -0,0 +1,168 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// ilaunchermgr.h
//
//==================================================================================================
#ifndef ILAUNCHERMGR_H
#define ILAUNCHERMGR_H
#ifdef _WIN32
#pragma once
#endif
#if defined( USE_SDL ) || defined( OSX )
#include "tier0/threadtools.h"
#include "appframework/IAppSystem.h"
#if defined( DX_TO_GL_ABSTRACTION )
#if defined( LINUX ) || defined( _WIN32 )
#include "togl/linuxwin/glmgrbasics.h"
#include "togl/linuxwin/glmdisplay.h"
#elif defined( OSX )
#include "togl/osx/glmgrbasics.h"
#include "togl/osx/glmdisplay.h"
#endif
class GLMDisplayDB;
class CShowPixelsParams;
#endif
// if you rev this version also update materialsystem/cmaterialsystem.cpp CMaterialSystem::Connect as it defines the string directly
#if defined( USE_SDL )
#define SDLMGR_INTERFACE_VERSION "SDLMgrInterface001"
#elif defined( OSX )
#define COCOAMGR_INTERFACE_VERSION "CocoaMgrInterface006"
#endif
class CCocoaEvent;
class CStackCrawlParams;
#if defined( USE_SDL )
typedef struct SDL_Cursor SDL_Cursor;
#endif
class ILauncherMgr : public IAppSystem
{
public:
virtual bool Connect( CreateInterfaceFn factory ) = 0;
virtual void Disconnect() = 0;
virtual void *QueryInterface( const char *pInterfaceName ) = 0;
// Init, shutdown
virtual InitReturnVal_t Init() = 0;
virtual void Shutdown() = 0;
// Create the window.
virtual bool CreateGameWindow( const char *pTitle, bool bWindowed, int width, int height ) = 0;
virtual void IncWindowRefCount() = 0;
virtual void DecWindowRefCount() = 0;
// Get the next N events. The function returns the number of events that were filled into your array.
virtual int GetEvents( CCocoaEvent *pEvents, int nMaxEventsToReturn, bool debugEvents = false ) = 0;
#ifdef LINUX
virtual int PeekAndRemoveKeyboardEvents( bool *pbEsc, bool *pbReturn, bool *pbSpace, bool debugEvents = false ) = 0;
#endif
// Set the mouse cursor position.
virtual void SetCursorPosition( int x, int y ) = 0;
virtual void SetWindowFullScreen( bool bFullScreen, int nWidth, int nHeight ) = 0;
virtual bool IsWindowFullScreen() = 0;
virtual void MoveWindow( int x, int y ) = 0;
virtual void SizeWindow( int width, int tall ) = 0;
virtual void PumpWindowsMessageLoop() = 0;
virtual void DestroyGameWindow() = 0;
virtual void SetApplicationIcon( const char *pchAppIconFile ) = 0;
virtual void GetMouseDelta( int &x, int &y, bool bIgnoreNextMouseDelta = false ) = 0;
virtual void GetNativeDisplayInfo( int nDisplay, uint &nWidth, uint &nHeight, uint &nRefreshHz ) = 0; // Retrieve the size of the monitor (desktop)
virtual void RenderedSize( uint &width, uint &height, bool set ) = 0; // either set or retrieve rendered size value (from dxabstract)
virtual void DisplayedSize( uint &width, uint &height ) = 0; // query backbuffer size (window size whether FS or windowed)
#if defined( DX_TO_GL_ABSTRACTION )
virtual PseudoGLContextPtr GetMainContext() = 0;
// Get the NSGLContext for a window's main view - note this is the carbon windowref as an argument
virtual PseudoGLContextPtr GetGLContextForWindow( void* windowref ) = 0;
virtual PseudoGLContextPtr CreateExtraContext() = 0;
virtual void DeleteContext( PseudoGLContextPtr hContext ) = 0;
virtual bool MakeContextCurrent( PseudoGLContextPtr hContext ) = 0;
virtual GLMDisplayDB *GetDisplayDB( void ) = 0;
virtual void GetDesiredPixelFormatAttribsAndRendererInfo( uint **ptrOut, uint *countOut, GLMRendererInfoFields *rendInfoOut ) = 0;
virtual void ShowPixels( CShowPixelsParams *params ) = 0;
#endif
virtual void GetStackCrawl( CStackCrawlParams *params ) = 0;
virtual void WaitUntilUserInput( int msSleepTime ) = 0;
virtual void *GetWindowRef() = 0;
virtual void SetMouseVisible( bool bState ) = 0;
#ifdef USE_SDL
virtual void SetMouseCursor( SDL_Cursor *hCursor ) = 0;
virtual void SetForbidMouseGrab( bool bForbidMouseGrab ) = 0;
virtual void OnFrameRendered() = 0;
#endif
virtual void SetGammaRamp( const uint16 *pRed, const uint16 *pGreen, const uint16 *pBlue ) = 0;
virtual double GetPrevGLSwapWindowTime() = 0;
};
extern ILauncherMgr *g_pLauncherMgr;
enum CocoaEventType_t
{
CocoaEvent_KeyDown,
CocoaEvent_KeyUp,
CocoaEvent_MouseButtonDown,
CocoaEvent_MouseMove,
CocoaEvent_MouseButtonUp,
CocoaEvent_AppActivate,
CocoaEvent_MouseScroll,
CocoaEvent_AppQuit,
CocoaEvent_Deleted, // Event was one of the above, but has been handled and should be ignored now.
};
// enum values need to match bit-shifting logic in CInputSystem::UpdateMouseButtonState and
// the codes from NSEvent pressedMouseButtons, turns out the two are in agreement right now
enum CocoaMouseButton_t
{
COCOABUTTON_LEFT = 1 << 0,
COCOABUTTON_RIGHT = 1 << 1,
COCOABUTTON_MIDDLE = 1 << 2,
COCOABUTTON_4 = 1 << 3,
COCOABUTTON_5 = 1 << 4,
};
enum ECocoaKeyModifier
{
eCapsLockKey,
eShiftKey,
eControlKey,
eAltKey, // aka option
eCommandKey
};
class CCocoaEvent
{
public:
CocoaEventType_t m_EventType;
int m_VirtualKeyCode;
wchar_t m_UnicodeKey;
wchar_t m_UnicodeKeyUnmodified;
uint m_ModifierKeyMask; //
int m_MousePos[2];
int m_MouseButtonFlags; // Current state of the mouse buttons. See COCOABUTTON_xxxx.
uint m_nMouseClickCount;
int m_MouseButton; // which of the CocoaMouseButton_t buttons this is for from above
};
#endif // USE_SDL || OSX
#endif // ILAUNCHERMGR_H

View File

@ -0,0 +1,85 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// The application object for apps that use tier2
//=============================================================================
#ifndef TIER2APP_H
#define TIER2APP_H
#ifdef _WIN32
#pragma once
#endif
#include "appframework/AppFramework.h"
#include "tier2/tier2dm.h"
#include "tier1/convar.h"
//-----------------------------------------------------------------------------
// The application object for apps that use tier2
//-----------------------------------------------------------------------------
class CTier2SteamApp : public CSteamAppSystemGroup
{
typedef CSteamAppSystemGroup BaseClass;
public:
// Methods of IApplication
virtual bool PreInit()
{
CreateInterfaceFn factory = GetFactory();
ConnectTier1Libraries( &factory, 1 );
ConVar_Register( 0 );
ConnectTier2Libraries( &factory, 1 );
return true;
}
virtual void PostShutdown()
{
DisconnectTier2Libraries();
ConVar_Unregister();
DisconnectTier1Libraries();
}
};
//-----------------------------------------------------------------------------
// The application object for apps that use tier2 and datamodel
//-----------------------------------------------------------------------------
class CTier2DmSteamApp : public CTier2SteamApp
{
typedef CTier2SteamApp BaseClass;
public:
// Methods of IApplication
virtual bool PreInit()
{
if ( !BaseClass::PreInit() )
return false;
CreateInterfaceFn factory = GetFactory();
if ( !ConnectDataModel( factory ) )
return false;
InitReturnVal_t nRetVal = InitDataModel();
return ( nRetVal == INIT_OK );
}
virtual void PostShutdown()
{
ShutdownDataModel();
DisconnectDataModel();
BaseClass::PostShutdown();
}
};
#endif // TIER2APP_H

View File

@ -0,0 +1,121 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// The application objects for apps that use tier3
//=============================================================================
#ifndef TIER3APP_H
#define TIER3APP_H
#ifdef _WIN32
#pragma once
#endif
#include "appframework/tier2app.h"
#include "tier3/tier3.h"
#include "vgui_controls/Controls.h"
//-----------------------------------------------------------------------------
// The application object for apps that use tier3
//-----------------------------------------------------------------------------
class CTier3SteamApp : public CTier2SteamApp
{
typedef CTier2SteamApp BaseClass;
public:
// Methods of IApplication
virtual bool PreInit()
{
if ( !BaseClass::PreInit() )
return false;
CreateInterfaceFn factory = GetFactory();
ConnectTier3Libraries( &factory, 1 );
return true;
}
virtual void PostShutdown()
{
DisconnectTier3Libraries();
BaseClass::PostShutdown();
}
};
//-----------------------------------------------------------------------------
// The application object for apps that use tier3
//-----------------------------------------------------------------------------
class CTier3DmSteamApp : public CTier2DmSteamApp
{
typedef CTier2DmSteamApp BaseClass;
public:
// Methods of IApplication
virtual bool PreInit()
{
if ( !BaseClass::PreInit() )
return false;
CreateInterfaceFn factory = GetFactory();
ConnectTier3Libraries( &factory, 1 );
return true;
}
virtual void PostShutdown()
{
DisconnectTier3Libraries();
BaseClass::PostShutdown();
}
};
//-----------------------------------------------------------------------------
// The application object for apps that use vgui
//-----------------------------------------------------------------------------
class CVguiSteamApp : public CTier3SteamApp
{
typedef CTier3SteamApp BaseClass;
public:
// Methods of IApplication
virtual bool PreInit()
{
if ( !BaseClass::PreInit() )
return false;
CreateInterfaceFn factory = GetFactory();
return vgui::VGui_InitInterfacesList( "CVguiSteamApp", &factory, 1 );
}
};
//-----------------------------------------------------------------------------
// The application object for apps that use vgui
//-----------------------------------------------------------------------------
class CVguiDmSteamApp : public CTier3DmSteamApp
{
typedef CTier3DmSteamApp BaseClass;
public:
// Methods of IApplication
virtual bool PreInit()
{
if ( !BaseClass::PreInit() )
return false;
CreateInterfaceFn factory = GetFactory();
return vgui::VGui_InitInterfacesList( "CVguiSteamApp", &factory, 1 );
}
};
#endif // TIER3APP_H

69
public/arraystack.h Normal file
View File

@ -0,0 +1,69 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef ARRAYSTACK_H
#define ARRAYSTACK_H
#pragma once
#include <assert.h>
#include "List.h"
template <class T> class ArrayStack
{
protected:
T *data;
int m_stackDepth;
int m_maxNumElements;
public:
ArrayStack( int maxNumElements )
{
data = new T[maxNumElements];
m_maxNumElements = maxNumElements;
m_stackDepth = 0;
assert( data );
}
void Push( T elem )
{
data[m_stackDepth++] = elem;
if( m_stackDepth > m_maxNumElements )
{
printf( "ArrayStack overflow\n" );
assert( 0 );
}
}
T Pop( void )
{
if( m_stackDepth == 0 )
{
printf( "ArrayStack underflow\n" );
assert( 0 );
}
return data[--m_stackDepth];
}
bool IsEmpty()
{
return ( m_stackDepth == 0 );
}
int GetDepth()
{
return m_stackDepth;
}
};
#endif // ARRAYSTACK_H

134
public/avi/iavi.h Normal file
View File

@ -0,0 +1,134 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
//=============================================================================
#ifndef IAVI_H
#define IAVI_H
#ifdef _WIN32
#pragma once
#endif
#include "appframework/IAppSystem.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct BGR888_t;
class IMaterial;
//-----------------------------------------------------------------------------
// Parameters for creating a new AVI
//-----------------------------------------------------------------------------
struct AVIParams_t
{
AVIParams_t() :
m_nFrameRate( 0 ), m_nFrameScale( 1 ), m_nWidth( 0 ), m_nHeight( 0 ),
m_nSampleRate( 0 ), m_nSampleBits( 0 ), m_nNumChannels( 0 ), m_bGetCodecFromUser( true )
{
m_pFileName[ 0 ] = 0;
}
char m_pFileName[ 256 ];
char m_pPathID[ 256 ];
// fps = m_nFrameRate / m_nFrameScale
// for integer framerates, set framerate to the fps, and framescale to 1
// for ntsc-style framerates like 29.97 (or 23.976 or 59.94),
// set framerate to 30,000 (or 24,000 or 60,000) and framescale to 1001
// yes, framescale is an odd naming choice, but it matching MS's AVI api
int m_nFrameRate;
int m_nFrameScale;
int m_nWidth;
int m_nHeight;
// Sound/.wav info
int m_nSampleRate;
int m_nSampleBits;
int m_nNumChannels;
// The user will be asked to select a compressor if true, otherwise the
// previous or default will be used.
bool m_bGetCodecFromUser;
};
//-----------------------------------------------------------------------------
// Handle to an AVI
//-----------------------------------------------------------------------------
typedef unsigned short AVIHandle_t;
enum
{
AVIHANDLE_INVALID = (AVIHandle_t)~0
};
//-----------------------------------------------------------------------------
// Handle to an AVI material
//-----------------------------------------------------------------------------
typedef unsigned short AVIMaterial_t;
enum
{
AVIMATERIAL_INVALID = (AVIMaterial_t)~0
};
//-----------------------------------------------------------------------------
// Main AVI interface
//-----------------------------------------------------------------------------
#define AVI_INTERFACE_VERSION "VAvi001"
class IAvi : public IAppSystem
{
public:
// Necessary to call this before any other AVI interface methods
virtual void SetMainWindow( void* hWnd ) = 0;
// Start/stop recording an AVI
virtual AVIHandle_t StartAVI( const AVIParams_t& params ) = 0;
virtual void FinishAVI( AVIHandle_t handle ) = 0;
// Add frames to an AVI
virtual void AppendMovieSound( AVIHandle_t h, short *buf, size_t bufsize ) = 0;
virtual void AppendMovieFrame( AVIHandle_t h, const BGR888_t *pRGBData ) = 0;
// Create/destroy an AVI material (a materialsystem IMaterial)
virtual AVIMaterial_t CreateAVIMaterial( const char *pMaterialName, const char *pFileName, const char *pPathID ) = 0;
virtual void DestroyAVIMaterial( AVIMaterial_t hMaterial ) = 0;
// Sets the time for an AVI material
virtual void SetTime( AVIMaterial_t hMaterial, float flTime ) = 0;
// Gets the IMaterial associated with an AVI material
virtual IMaterial* GetMaterial( AVIMaterial_t hMaterial ) = 0;
// Returns the max texture coordinate of the AVI
virtual void GetTexCoordRange( AVIMaterial_t hMaterial, float *pMaxU, float *pMaxV ) = 0;
// Returns the frame size of the AVI (stored in a subrect of the material itself)
virtual void GetFrameSize( AVIMaterial_t hMaterial, int *pWidth, int *pHeight ) = 0;
// Returns the frame rate of the AVI
virtual int GetFrameRate( AVIMaterial_t hMaterial ) = 0;
// Returns the total frame count of the AVI
virtual int GetFrameCount( AVIMaterial_t hMaterial ) = 0;
// Sets the frame for an AVI material (use instead of SetTime)
virtual void SetFrame( AVIMaterial_t hMaterial, float flFrame ) = 0;
// Plays a given AVI/WMV file until it completes or the user presses ESC, SPACE, or ENTER
virtual void PlayWindowsMediaVideo( const char *filename, void *mainWindow, int width, int height, float forcedMinTime ) = 0;
};
#endif // IAVI_H

174
public/avi/iquicktime.h Normal file
View File

@ -0,0 +1,174 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
//=============================================================================
#ifndef IQUICKTIME_H
#define IQUICKTIME_H
#ifdef _WIN32
#pragma once
#endif
#include "appframework/IAppSystem.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct BGR888_t;
class IMaterial;
//-----------------------------------------------------------------------------
// Handle to a QUICKTIME
//-----------------------------------------------------------------------------
typedef unsigned short QUICKTIMEHandle_t;
enum
{
QUICKTIMEHANDLE_INVALID = (QUICKTIMEHandle_t)~0
};
//-----------------------------------------------------------------------------
// Handle to an QUICKTIME material
//-----------------------------------------------------------------------------
typedef unsigned short QUICKTIMEMaterial_t;
enum
{
QUICKTIMEMATERIAL_INVALID = (QUICKTIMEMaterial_t)~0
};
typedef unsigned int MovieHandle_t;
const MovieHandle_t cInvalidMovieHandle = (MovieHandle_t) ~0;
enum eVideoSystemStatus
{
cVideoSystem_OK = 0,
cVideoSystem_NotInstalled,
cVideoSystem_NotCurrentVersion,
cVideoSystem_InitializationError,
cVideoSystem_ForceInt32 = 0x7FFFFFFF // Make sure eNum is (at least) an int32
};
enum eVideoSystemFeatures
{
cVideoSystem_NoFeatures = 0x00000000,
cVideoSystem_PlayMoviesFromFile = 0x00000001,
cVideoSystem_RenderVideoFrameToMaterial = 0x00000002,
cVideoSystem_EncodeVideoToFile = 0x00000010,
cVideoSystem_EncodeAudioToFile = 0x00000020,
cVideoSystem_ForceInt32a = 0x7FFFFFFF
};
DEFINE_ENUM_BITWISE_OPERATORS( eVideoSystemFeatures );
enum eVideoEncodeQuality
{
cVEQuality_Min = 0,
cVEQuality_Low = 25,
cVEQuality_Normal = 50,
cVEQuality_High = 75,
cVEQuality_Max = 100
};
// -----------------------------------------------------------------------
// eVideoFrameFormat_t - bit format for quicktime video frames
// -----------------------------------------------------------------------
enum eVideoFrameFormat_t
{
cVFF_Undefined = 0,
cVFF_R8G8B8A8_32Bit,
cVFF_R8G8B8_24Bit,
cVFF_Count, // Auto list counter
cVFF_ForceInt32 = 0x7FFFFFFF // Make sure eNum is (at least) an int32
};
// -----------------------------------------------------------------------
// eAudioSourceFormat_t - Audio encoding source options
// -----------------------------------------------------------------------
enum eAudioSourceFormat_t
{
cASF_Undefined = 0,
cASF_None,
cASF_16BitPCMStereo,
cASF_Count, // Auto list counter
cASF_ForceInt32 = 0x7FFFFFFF // Make sure eNum is (at least) an int32
};
//-----------------------------------------------------------------------------
// IQuickTimeMovieMaker interface
//-----------------------------------------------------------------------------
class IQuickTimeMovieMaker : public IBaseInterface
{
public:
virtual bool CreateNewMovieFile( MovieHandle_t &theMovie, const char *pFilename, int nWidth, int nHeight, int nFps, eVideoEncodeQuality quality, eAudioSourceFormat_t srcAudioFormat = cASF_None, int audioSampleRate = 0 ) = 0;
virtual bool AppendVideoFrame( MovieHandle_t theMovie, unsigned char *pFrame ) = 0;
virtual bool AppendAudioSamples( MovieHandle_t theMovie, void *sampleBuffer, size_t sampleSize ) = 0;
virtual bool FinishMovie( MovieHandle_t theMovie, bool success = true ) = 0;
};
//-----------------------------------------------------------------------------
// Main QUICKTIME interface
//-----------------------------------------------------------------------------
#define QUICKTIME_INTERFACE_VERSION "IQuickTime002"
class IQuickTime : public IAppSystem
{
public:
virtual bool IsVideoSystemAvailable() = 0;
virtual eVideoSystemStatus GetVideoSystemStatus() = 0;
virtual eVideoSystemFeatures GetVideoSystemFeatures() = 0;
// Create/destroy a QUICKTIME material (a materialsystem IMaterial)
virtual QUICKTIMEMaterial_t CreateMaterial( const char *pMaterialName, const char *pFileName, const char *pPathID ) = 0;
virtual void DestroyMaterial( QUICKTIMEMaterial_t hMaterial ) = 0;
// Create/destroy a quicktime movie maker, which will encode audio/video
virtual IQuickTimeMovieMaker *CreateMovieMaker() = 0;
virtual void DestroyMovieMaker( IQuickTimeMovieMaker *&pMovieMaker ) = 0;
// Update the frame (if necessary)
virtual bool Update( QUICKTIMEMaterial_t hMaterial ) = 0;
// Gets the IMaterial associated with an BINK material
virtual IMaterial* GetMaterial( QUICKTIMEMaterial_t hMaterial ) = 0;
// Returns the max texture coordinate of the BINK
virtual void GetTexCoordRange( QUICKTIMEMaterial_t hMaterial, float *pMaxU, float *pMaxV ) = 0;
// Returns the frame size of the QUICKTIME Image Frame (stored in a subrect of the material itself)
virtual void GetFrameSize( QUICKTIMEMaterial_t hMaterial, int *pWidth, int *pHeight ) = 0;
// Returns the frame rate of the QUICKTIME
virtual int GetFrameRate( QUICKTIMEMaterial_t hMaterial ) = 0;
// Sets the frame for an BINK material (use instead of SetTime)
virtual void SetFrame( QUICKTIMEMaterial_t hMaterial, float flFrame ) = 0;
// Returns the total frame count of the BINK
virtual int GetFrameCount( QUICKTIMEMaterial_t hMaterial ) = 0;
virtual bool SetSoundDevice( void *pDevice ) = 0;
// Plays a given MOV file until it completes or the user presses ESC, SPACE, or ENTER
virtual void PlayQuicktimeVideo( const char *filename, void *mainWindow, int windowWidth, int windowHeight, int desktopWidth, int desktopHeight, bool windowed, float forcedMinTime ) = 0;
// Estimates the size of a recorded movie
virtual bool EstimateMovieSize( unsigned long &EstSize, int nWidth, int nHeight, int nFps, float duration, eVideoEncodeQuality quality, eAudioSourceFormat_t srcAudioFormat = cASF_None, int audioSampleRate = 0 ) = 0;
};
#endif // IQUICKTIME_H

177
public/basehandle.h Normal file
View File

@ -0,0 +1,177 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef BASEHANDLE_H
#define BASEHANDLE_H
#ifdef _WIN32
#pragma once
#endif
#include "const.h"
#include "tier0/dbg.h"
class IHandleEntity;
// -------------------------------------------------------------------------------------------------- //
// CBaseHandle.
// -------------------------------------------------------------------------------------------------- //
class CBaseHandle
{
friend class CBaseEntityList;
public:
CBaseHandle();
CBaseHandle( const CBaseHandle &other );
CBaseHandle( unsigned long value );
CBaseHandle( int iEntry, int iSerialNumber );
void Init( int iEntry, int iSerialNumber );
void Term();
// Even if this returns true, Get() still can return return a non-null value.
// This just tells if the handle has been initted with any values.
bool IsValid() const;
int GetEntryIndex() const;
int GetSerialNumber() const;
int ToInt() const;
bool operator !=( const CBaseHandle &other ) const;
bool operator ==( const CBaseHandle &other ) const;
bool operator ==( const IHandleEntity* pEnt ) const;
bool operator !=( const IHandleEntity* pEnt ) const;
bool operator <( const CBaseHandle &other ) const;
bool operator <( const IHandleEntity* pEnt ) const;
// Assign a value to the handle.
const CBaseHandle& operator=( const IHandleEntity *pEntity );
const CBaseHandle& Set( const IHandleEntity *pEntity );
// Use this to dereference the handle.
// Note: this is implemented in game code (ehandle.h)
IHandleEntity* Get() const;
protected:
// The low NUM_SERIAL_BITS hold the index. If this value is less than MAX_EDICTS, then the entity is networkable.
// The high NUM_SERIAL_NUM_BITS bits are the serial number.
unsigned long m_Index;
};
#include "ihandleentity.h"
inline CBaseHandle::CBaseHandle()
{
m_Index = INVALID_EHANDLE_INDEX;
}
inline CBaseHandle::CBaseHandle( const CBaseHandle &other )
{
m_Index = other.m_Index;
}
inline CBaseHandle::CBaseHandle( unsigned long value )
{
m_Index = value;
}
inline CBaseHandle::CBaseHandle( int iEntry, int iSerialNumber )
{
Init( iEntry, iSerialNumber );
}
inline void CBaseHandle::Init( int iEntry, int iSerialNumber )
{
Assert( iEntry >= 0 && iEntry < NUM_ENT_ENTRIES );
Assert( iSerialNumber >= 0 && iSerialNumber < (1 << NUM_SERIAL_NUM_BITS) );
m_Index = iEntry | (iSerialNumber << NUM_ENT_ENTRY_BITS);
}
inline void CBaseHandle::Term()
{
m_Index = INVALID_EHANDLE_INDEX;
}
inline bool CBaseHandle::IsValid() const
{
return m_Index != INVALID_EHANDLE_INDEX;
}
inline int CBaseHandle::GetEntryIndex() const
{
return m_Index & ENT_ENTRY_MASK;
}
inline int CBaseHandle::GetSerialNumber() const
{
return m_Index >> NUM_ENT_ENTRY_BITS;
}
inline int CBaseHandle::ToInt() const
{
return (int)m_Index;
}
inline bool CBaseHandle::operator !=( const CBaseHandle &other ) const
{
return m_Index != other.m_Index;
}
inline bool CBaseHandle::operator ==( const CBaseHandle &other ) const
{
return m_Index == other.m_Index;
}
inline bool CBaseHandle::operator ==( const IHandleEntity* pEnt ) const
{
return Get() == pEnt;
}
inline bool CBaseHandle::operator !=( const IHandleEntity* pEnt ) const
{
return Get() != pEnt;
}
inline bool CBaseHandle::operator <( const CBaseHandle &other ) const
{
return m_Index < other.m_Index;
}
inline bool CBaseHandle::operator <( const IHandleEntity *pEntity ) const
{
unsigned long otherIndex = (pEntity) ? pEntity->GetRefEHandle().m_Index : INVALID_EHANDLE_INDEX;
return m_Index < otherIndex;
}
inline const CBaseHandle& CBaseHandle::operator=( const IHandleEntity *pEntity )
{
return Set( pEntity );
}
inline const CBaseHandle& CBaseHandle::Set( const IHandleEntity *pEntity )
{
if ( pEntity )
{
*this = pEntity->GetRefEHandle();
}
else
{
m_Index = INVALID_EHANDLE_INDEX;
}
return *this;
}
#endif // BASEHANDLE_H

142
public/bitmap/bitmap.h Normal file
View File

@ -0,0 +1,142 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Header: $
// $NoKeywords: $
//===========================================================================//
#ifndef BITMAP_H
#define BITMAP_H
#ifdef _WIN32
#pragma once
#endif
#include "bitmap/imageformat.h"
#include "Color.h"
#include "dbg.h"
class CUtlBuffer;
//-----------------------------------------------------------------------------
// A Bitmap
//-----------------------------------------------------------------------------
struct Bitmap_t
{
Bitmap_t() { Reset(); }
~Bitmap_t() { Clear(); }
//
// Accessors
//
inline int Width() const { return m_nWidth; }
inline int Height() const { return m_nHeight; }
inline ImageFormat Format() const { return m_ImageFormat; }
inline unsigned char *GetBits() const { return m_pBits; }
inline int Stride() const { return m_nStride; }
inline bool GetOwnsBuffer() const { return m_bOwnsBuffer; }
/// Allocate the buffer. Discards existing data, freeing it if we own it
void Init( int nWidth, int nHeight, ImageFormat imageFormat, int nStride = 0 );
/// Set the bitmap to the specified buffer. Any existing data is discarded/freed
/// as appropriate.
void SetBuffer( int nWidth, int nHeight, ImageFormat imageFormat, unsigned char *pBits, bool bAssumeOwnership, int nStride = 0 );
/// Sets / releases ownershp of the buffer. This does not otherwise alter the
/// state of the bitmap.
void SetOwnsBuffer( bool bOwnsBuffer )
{
Assert( m_pBits );
m_bOwnsBuffer = bOwnsBuffer;
}
/// Free up all memory and reset to default state
void Clear();
/// Return true if we have a valid size and buffer
bool IsValid() const;
/// Get pointer to raw pixel data.
unsigned char *GetPixel( int x, int y );
const unsigned char *GetPixel( int x, int y ) const;
/// Get pixel value at specified coordinates
Color GetColor( int x, int y ) const;
/// Set pixel value at specified coordinates
void SetColor( int x, int y, Color c );
/// Set this bitmap to be a logical copy of the specified
/// bitmap. No memory is allocated or copied, just copying
/// some pointers. We can also optionally transfer ownership
/// of the buffer.
void MakeLogicalCopyOf( Bitmap_t &src, bool bTransferBufferOwnership = false );
/// Set this bitmap to be a cropped rectangle from the given bitmap.
/// The source pointer can be NULL or point to this, which means to do
/// the crop in place.
void Crop( int x0, int y0, int nWidth, int nHeight, const Bitmap_t *pImgSource = NULL );
/// Blit a rectangle of pixel data into this image.
void SetPixelData( const Bitmap_t &src, int nSrcX1, int nSrcY1, int nCopySizeX, int nCopySizeY, int nDestX1, int nDestY1 );
/// Blit the entire source image into this image, at the specified offset.
/// the rectangle is clipped if necessary
void SetPixelData( const Bitmap_t &src, int nDestX1 = 0, int nDestY1 = 0 );
private:
void Reset();
/// Dimensions
int m_nWidth;
int m_nHeight;
/// Size, in bytes, of one pixel
int m_nPixelSize;
/// Image row stride, in bytes
int m_nStride;
// Do we own this buffer?
bool m_bOwnsBuffer;
/// Pixel format
ImageFormat m_ImageFormat;
/// Bitmap data. Must be allocated with malloc/free. Don't use
/// new/delete
unsigned char *m_pBits;
};
inline void Bitmap_t::Reset()
{
m_nWidth = 0;
m_nHeight = 0;
m_ImageFormat = IMAGE_FORMAT_UNKNOWN;
m_pBits = NULL;
m_nPixelSize = 0;
m_bOwnsBuffer = false;
m_nStride = 0;
}
inline unsigned char *Bitmap_t::GetPixel( int x, int y )
{
if ( !m_pBits )
return NULL;
return m_pBits + (y*m_nStride) + x* m_nPixelSize;
}
inline const unsigned char *Bitmap_t::GetPixel( int x, int y ) const
{
if ( !m_pBits )
return NULL;
return m_pBits + (y*m_nStride) + x* m_nPixelSize;
}
#endif // BITMAP_H

68
public/bitmap/cubemap.h Normal file
View File

@ -0,0 +1,68 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: a class for performing cube-mapped spherical sample lookups.
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
#ifndef CUBEMAP_H
#define CUBEMAP_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/platform.h"
#include "tier1/utlmemory.h"
#include "mathlib/mathlib.h"
template<class T, int RES> struct CCubeMap
{
T m_Samples[6][RES][RES];
public:
FORCEINLINE void GetCoords( Vector const &vecNormalizedDirection, int &nX, int &nY, int &nFace )
{
// find largest magnitude component
int nLargest = 0;
int nAxis0 = 1;
int nAxis1 = 2;
if ( fabs( vecNormalizedDirection[1] ) > fabs( vecNormalizedDirection[0] ) )
{
nLargest = 1;
nAxis0 = 0;
nAxis1 = 2;
}
if ( fabs( vecNormalizedDirection[2] ) > fabs( vecNormalizedDirection[nLargest] ) )
{
nLargest = 2;
nAxis0 = 0;
nAxis1 = 1;
}
float flZ = vecNormalizedDirection[nLargest];
if ( flZ < 0 )
{
flZ = - flZ;
nLargest += 3;
}
nFace = nLargest;
flZ = 1.0 / flZ;
nX = RemapValClamped( vecNormalizedDirection[nAxis0] * flZ, -1, 1, 0, RES - 1 );
nY = RemapValClamped( vecNormalizedDirection[nAxis1] * flZ, -1, 1, 0, RES - 1 );
}
FORCEINLINE T & GetSample( Vector const &vecNormalizedDirection )
{
int nX, nY, nFace;
GetCoords( vecNormalizedDirection, nX, nY, nFace );
return m_Samples[nFace][nX][nY];
}
};
#endif // CUBEMAP_H

363
public/bitmap/float_bm.h Normal file
View File

@ -0,0 +1,363 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Header: $
// $NoKeywords: $
//=============================================================================//
#ifndef FLOAT_BM_H
#define FLOAT_BM_H
#ifdef _WIN32
#pragma once
#endif
#include <tier0/platform.h>
#include "tier0/dbg.h"
#include <mathlib/mathlib.h>
struct PixRGBAF
{
float Red;
float Green;
float Blue;
float Alpha;
};
struct PixRGBA8
{
unsigned char Red;
unsigned char Green;
unsigned char Blue;
unsigned char Alpha;
};
inline PixRGBAF PixRGBA8_to_F( PixRGBA8 const &x )
{
PixRGBAF f;
f.Red = x.Red / float( 255.0f );
f.Green = x.Green / float( 255.0f );
f.Blue = x.Blue / float( 255.0f );
f.Alpha = x.Alpha / float( 255.0f );
return f;
}
inline PixRGBA8 PixRGBAF_to_8( PixRGBAF const &f )
{
PixRGBA8 x;
x.Red = max( 0, min( 255.0,255.0*f.Red ) );
x.Green = max( 0, min( 255.0,255.0*f.Green ) );
x.Blue = max( 0, min( 255.0,255.0*f.Blue ) );
x.Alpha = max( 0, min( 255.0,255.0*f.Alpha ) );
return x;
}
#define SPFLAGS_MAXGRADIENT 1
// bit flag options for ComputeSelfShadowedBumpmapFromHeightInAlphaChannel:
#define SSBUMP_OPTION_NONDIRECTIONAL 1 // generate ambient occlusion only
#define SSBUMP_MOD2X_DETAIL_TEXTURE 2 // scale so that a flat unshadowed
// value is 0.5, and bake rgb luminance
// in.
class FloatBitMap_t
{
public:
int Width, Height; // bitmap dimensions
float *RGBAData; // actual data
FloatBitMap_t(void) // empty one
{
Width=Height=0;
RGBAData=0;
}
FloatBitMap_t(int width, int height); // make one and allocate space
FloatBitMap_t(char const *filename); // read one from a file (tga or pfm)
FloatBitMap_t(FloatBitMap_t const *orig);
// quantize one to 8 bits
bool WriteTGAFile(char const *filename) const;
bool LoadFromPFM(char const *filename); // load from floating point pixmap (.pfm) file
bool WritePFM(char const *filename); // save to floating point pixmap (.pfm) file
void InitializeWithRandomPixelsFromAnotherFloatBM(FloatBitMap_t const &other);
inline float & Pixel(int x, int y, int comp) const
{
Assert((x>=0) && (x<Width));
Assert((y>=0) && (y<Height));
return RGBAData[4*(x+Width*y)+comp];
}
inline float & PixelWrapped(int x, int y, int comp) const
{
// like Pixel except wraps around to other side
if (x < 0)
x+=Width;
else
if (x>= Width)
x -= Width;
if ( y < 0 )
y+=Height;
else
if ( y >= Height )
y -= Height;
return RGBAData[4*(x+Width*y)+comp];
}
inline float & PixelClamped(int x, int y, int comp) const
{
// like Pixel except wraps around to other side
x=clamp(x,0,Width-1);
y=clamp(y,0,Height-1);
return RGBAData[4*(x+Width*y)+comp];
}
inline float & Alpha(int x, int y) const
{
Assert((x>=0) && (x<Width));
Assert((y>=0) && (y<Height));
return RGBAData[3+4*(x+Width*y)];
}
// look up a pixel value with bilinear interpolation
float InterpolatedPixel(float x, float y, int comp) const;
inline PixRGBAF PixelRGBAF(int x, int y) const
{
Assert((x>=0) && (x<Width));
Assert((y>=0) && (y<Height));
PixRGBAF RetPix;
int RGBoffset= 4*(x+Width*y);
RetPix.Red= RGBAData[RGBoffset+0];
RetPix.Green= RGBAData[RGBoffset+1];
RetPix.Blue= RGBAData[RGBoffset+2];
RetPix.Alpha= RGBAData[RGBoffset+3];
return RetPix;
}
inline void WritePixelRGBAF(int x, int y, PixRGBAF value) const
{
Assert((x>=0) && (x<Width));
Assert((y>=0) && (y<Height));
int RGBoffset= 4*(x+Width*y);
RGBAData[RGBoffset+0]= value.Red;
RGBAData[RGBoffset+1]= value.Green;
RGBAData[RGBoffset+2]= value.Blue;
RGBAData[RGBoffset+3]= value.Alpha;
}
inline void WritePixel(int x, int y, int comp, float value)
{
Assert((x>=0) && (x<Width));
Assert((y>=0) && (y<Height));
RGBAData[4*(x+Width*y)+comp]= value;
}
// paste, performing boundary matching. Alpha channel can be used to make
// brush shape irregular
void SmartPaste(FloatBitMap_t const &brush, int xofs, int yofs, uint32 flags);
// force to be tileable using poisson formula
void MakeTileable(void);
void ReSize(int NewXSize, int NewYSize);
// find the bounds of the area that has non-zero alpha.
void GetAlphaBounds(int &minx, int &miny, int &maxx,int &maxy);
// Solve the poisson equation for an image. The alpha channel of the image controls which
// pixels are "modifiable", and can be used to set boundary conditions. Alpha=0 means the pixel
// is locked. deltas are in the order [(x,y)-(x,y-1),(x,y)-(x-1,y),(x,y)-(x+1,y),(x,y)-(x,y+1)
void Poisson(FloatBitMap_t *deltas[4],
int n_iters,
uint32 flags // SPF_xxx
);
FloatBitMap_t *QuarterSize(void) const; // get a new one downsampled
FloatBitMap_t *QuarterSizeBlocky(void) const; // get a new one downsampled
FloatBitMap_t *QuarterSizeWithGaussian(void) const; // downsample 2x using a gaussian
void RaiseToPower(float pow);
void ScaleGradients(void);
void Logize(void); // pix=log(1+pix)
void UnLogize(void); // pix=exp(pix)-1
// compress to 8 bits converts the hdr texture to an 8 bit texture, encoding a scale factor
// in the alpha channel. upon return, the original pixel can be (approximately) recovered
// by the formula rgb*alpha*overbright.
// this function performs special numerical optimization on the texture to minimize the error
// when using bilinear filtering to read the texture.
void CompressTo8Bits(float overbright);
// decompress a bitmap converted by CompressTo8Bits
void Uncompress(float overbright);
Vector AverageColor(void); // average rgb value of all pixels
float BrightestColor(void); // highest vector magnitude
void Clear(float r, float g, float b, float alpha); // set all pixels to speicifed values (0..1 nominal)
void ScaleRGB(float scale_factor); // for all pixels, r,g,b*=scale_factor
// given a bitmap with height stored in the alpha channel, generate vector positions and normals
void ComputeVertexPositionsAndNormals( float flHeightScale, Vector **ppPosOut, Vector **ppNormalOut ) const;
// generate a normal map with height stored in alpha. uses hl2 tangent basis to support baked
// self shadowing. the bump scale maps the height of a pixel relative to the edges of the
// pixel. This function may take a while - many millions of rays may be traced. applications
// using this method need to link w/ raytrace.lib
FloatBitMap_t *ComputeSelfShadowedBumpmapFromHeightInAlphaChannel(
float bump_scale, int nrays_to_trace_per_pixel=100,
uint32 nOptionFlags = 0 // SSBUMP_OPTION_XXX
) const;
// generate a conventional normal map from a source with height stored in alpha.
FloatBitMap_t *ComputeBumpmapFromHeightInAlphaChannel( float bump_scale ) const ;
// bilateral (edge preserving) smoothing filter. edge_threshold_value defines the difference in
// values over which filtering will not occur. Each channel is filtered independently. large
// radii will run slow, since the bilateral filter is neither separable, nor is it a
// convolution that can be done via fft.
void TileableBilateralFilter( int radius_in_pixels, float edge_threshold_value );
~FloatBitMap_t();
void AllocateRGB(int w, int h)
{
if (RGBAData) delete[] RGBAData;
RGBAData=new float[w*h*4];
Width=w;
Height=h;
}
};
// a FloatCubeMap_t holds the floating point bitmaps for 6 faces of a cube map
class FloatCubeMap_t
{
public:
FloatBitMap_t face_maps[6];
FloatCubeMap_t(int xfsize, int yfsize)
{
// make an empty one with face dimensions xfsize x yfsize
for(int f=0;f<6;f++)
face_maps[f].AllocateRGB(xfsize,yfsize);
}
// load basenamebk,pfm, basenamedn.pfm, basenameft.pfm, ...
FloatCubeMap_t(char const *basename);
// save basenamebk,pfm, basenamedn.pfm, basenameft.pfm, ...
void WritePFMs(char const *basename);
Vector AverageColor(void)
{
Vector ret(0,0,0);
int nfaces=0;
for(int f=0;f<6;f++)
if (face_maps[f].RGBAData)
{
nfaces++;
ret+=face_maps[f].AverageColor();
}
if (nfaces)
ret*=(1.0/nfaces);
return ret;
}
float BrightestColor(void)
{
float ret=0.0;
int nfaces=0;
for(int f=0;f<6;f++)
if (face_maps[f].RGBAData)
{
nfaces++;
ret=max(ret,face_maps[f].BrightestColor());
}
return ret;
}
// resample a cubemap to one of possibly a lower resolution, using a given phong exponent.
// dot-product weighting will be used for the filtering operation.
void Resample(FloatCubeMap_t &dest, float flPhongExponent);
// returns the normalized direciton vector through a given pixel of a given face
Vector PixelDirection(int face, int x, int y);
// returns the direction vector throught the center of a cubemap face
Vector FaceNormal( int nFaceNumber );
};
static inline float FLerp(float f1, float f2, float t)
{
return f1+(f2-f1)*t;
}
// Image Pyramid class.
#define MAX_IMAGE_PYRAMID_LEVELS 16 // up to 64kx64k
enum ImagePyramidMode_t
{
PYRAMID_MODE_GAUSSIAN,
};
class FloatImagePyramid_t
{
public:
int m_nLevels;
FloatBitMap_t *m_pLevels[MAX_IMAGE_PYRAMID_LEVELS]; // level 0 is highest res
FloatImagePyramid_t(void)
{
m_nLevels=0;
memset(m_pLevels,0,sizeof(m_pLevels));
}
// build one. clones data from src for level 0.
FloatImagePyramid_t(FloatBitMap_t const &src, ImagePyramidMode_t mode);
// read or write a Pixel from a given level. All coordinates are specified in the same domain as the base level.
float &Pixel(int x, int y, int component, int level) const;
FloatBitMap_t *Level(int lvl) const
{
Assert(lvl<m_nLevels);
Assert(lvl<ARRAYSIZE(m_pLevels));
return m_pLevels[lvl];
}
// rebuild all levels above the specified level
void ReconstructLowerResolutionLevels(int starting_level);
~FloatImagePyramid_t(void);
void WriteTGAs(char const *basename) const; // outputs name_00.tga, name_01.tga,...
};
#endif

518
public/bitmap/imageformat.h Normal file
View File

@ -0,0 +1,518 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#ifndef IMAGEFORMAT_H
#define IMAGEFORMAT_H
#ifdef _WIN32
#pragma once
#endif
#include <stdio.h>
enum NormalDecodeMode_t
{
NORMAL_DECODE_NONE = 0,
NORMAL_DECODE_ATI2N = 1,
NORMAL_DECODE_ATI2N_ALPHA = 2
};
// Forward declaration
#ifdef _WIN32
typedef enum _D3DFORMAT D3DFORMAT;
#endif
//-----------------------------------------------------------------------------
// The various image format types
//-----------------------------------------------------------------------------
// don't bitch that inline functions aren't used!!!!
#pragma warning(disable : 4514)
enum ImageFormat
{
IMAGE_FORMAT_UNKNOWN = -1,
IMAGE_FORMAT_RGBA8888 = 0,
IMAGE_FORMAT_ABGR8888,
IMAGE_FORMAT_RGB888,
IMAGE_FORMAT_BGR888,
IMAGE_FORMAT_RGB565,
IMAGE_FORMAT_I8,
IMAGE_FORMAT_IA88,
IMAGE_FORMAT_P8,
IMAGE_FORMAT_A8,
IMAGE_FORMAT_RGB888_BLUESCREEN,
IMAGE_FORMAT_BGR888_BLUESCREEN,
IMAGE_FORMAT_ARGB8888,
IMAGE_FORMAT_BGRA8888,
IMAGE_FORMAT_DXT1,
IMAGE_FORMAT_DXT3,
IMAGE_FORMAT_DXT5,
IMAGE_FORMAT_BGRX8888,
IMAGE_FORMAT_BGR565,
IMAGE_FORMAT_BGRX5551,
IMAGE_FORMAT_BGRA4444,
IMAGE_FORMAT_DXT1_ONEBITALPHA,
IMAGE_FORMAT_BGRA5551,
IMAGE_FORMAT_UV88,
IMAGE_FORMAT_UVWQ8888,
IMAGE_FORMAT_RGBA16161616F,
IMAGE_FORMAT_RGBA16161616,
IMAGE_FORMAT_UVLX8888,
IMAGE_FORMAT_R32F, // Single-channel 32-bit floating point
IMAGE_FORMAT_RGB323232F,
IMAGE_FORMAT_RGBA32323232F,
// Depth-stencil texture formats for shadow depth mapping
IMAGE_FORMAT_NV_DST16, //
IMAGE_FORMAT_NV_DST24, //
IMAGE_FORMAT_NV_INTZ, // Vendor-specific depth-stencil texture
IMAGE_FORMAT_NV_RAWZ, // formats for shadow depth mapping
IMAGE_FORMAT_ATI_DST16, //
IMAGE_FORMAT_ATI_DST24, //
IMAGE_FORMAT_NV_NULL, // Dummy format which takes no video memory
// Compressed normal map formats
IMAGE_FORMAT_ATI2N, // One-surface ATI2N / DXN format
IMAGE_FORMAT_ATI1N, // Two-surface ATI1N format
#if defined( _X360 )
// Depth-stencil texture formats
IMAGE_FORMAT_X360_DST16,
IMAGE_FORMAT_X360_DST24,
IMAGE_FORMAT_X360_DST24F,
// supporting these specific formats as non-tiled for procedural cpu access
IMAGE_FORMAT_LINEAR_BGRX8888,
IMAGE_FORMAT_LINEAR_RGBA8888,
IMAGE_FORMAT_LINEAR_ABGR8888,
IMAGE_FORMAT_LINEAR_ARGB8888,
IMAGE_FORMAT_LINEAR_BGRA8888,
IMAGE_FORMAT_LINEAR_RGB888,
IMAGE_FORMAT_LINEAR_BGR888,
IMAGE_FORMAT_LINEAR_BGRX5551,
IMAGE_FORMAT_LINEAR_I8,
IMAGE_FORMAT_LINEAR_RGBA16161616,
IMAGE_FORMAT_LE_BGRX8888,
IMAGE_FORMAT_LE_BGRA8888,
#endif
NUM_IMAGE_FORMATS
};
#if defined( POSIX ) || defined( DX_TO_GL_ABSTRACTION )
typedef enum _D3DFORMAT
{
D3DFMT_INDEX16,
D3DFMT_D16,
D3DFMT_D24S8,
D3DFMT_A8R8G8B8,
D3DFMT_A4R4G4B4,
D3DFMT_X8R8G8B8,
D3DFMT_R5G6R5,
D3DFMT_X1R5G5B5,
D3DFMT_A1R5G5B5,
D3DFMT_L8,
D3DFMT_A8L8,
D3DFMT_A,
D3DFMT_DXT1,
D3DFMT_DXT3,
D3DFMT_DXT5,
D3DFMT_V8U8,
D3DFMT_Q8W8V8U8,
D3DFMT_X8L8V8U8,
D3DFMT_A16B16G16R16F,
D3DFMT_A16B16G16R16,
D3DFMT_R32F,
D3DFMT_A32B32G32R32F,
D3DFMT_R8G8B8,
D3DFMT_D24X4S4,
D3DFMT_A8,
D3DFMT_R5G6B5,
D3DFMT_D15S1,
D3DFMT_D24X8,
D3DFMT_VERTEXDATA,
D3DFMT_INDEX32,
// adding fake D3D format names for the vendor specific ones (eases debugging/logging)
// NV shadow depth tex
D3DFMT_NV_INTZ = 0x5a544e49, // MAKEFOURCC('I','N','T','Z')
D3DFMT_NV_RAWZ = 0x5a574152, // MAKEFOURCC('R','A','W','Z')
// NV null tex
D3DFMT_NV_NULL = 0x4c4c554e, // MAKEFOURCC('N','U','L','L')
// ATI shadow depth tex
D3DFMT_ATI_D16 = 0x36314644, // MAKEFOURCC('D','F','1','6')
D3DFMT_ATI_D24S8 = 0x34324644, // MAKEFOURCC('D','F','2','4')
// ATI 1N and 2N compressed tex
D3DFMT_ATI_2N = 0x32495441, // MAKEFOURCC('A', 'T', 'I', '2')
D3DFMT_ATI_1N = 0x31495441, // MAKEFOURCC('A', 'T', 'I', '1')
D3DFMT_UNKNOWN
} D3DFORMAT;
#endif
//-----------------------------------------------------------------------------
// Color structures
//-----------------------------------------------------------------------------
struct BGRA8888_t
{
unsigned char b; // change the order of names to change the
unsigned char g; // order of the output ARGB or BGRA, etc...
unsigned char r; // Last one is MSB, 1st is LSB.
unsigned char a;
inline BGRA8888_t& operator=( const BGRA8888_t& in )
{
*( unsigned int * )this = *( unsigned int * )&in;
return *this;
}
};
struct RGBA8888_t
{
unsigned char r; // change the order of names to change the
unsigned char g; // order of the output ARGB or BGRA, etc...
unsigned char b; // Last one is MSB, 1st is LSB.
unsigned char a;
inline RGBA8888_t& operator=( const BGRA8888_t& in )
{
r = in.r;
g = in.g;
b = in.b;
a = in.a;
return *this;
}
};
struct RGB888_t
{
unsigned char r;
unsigned char g;
unsigned char b;
inline RGB888_t& operator=( const BGRA8888_t& in )
{
r = in.r;
g = in.g;
b = in.b;
return *this;
}
inline bool operator==( const RGB888_t& in ) const
{
return ( r == in.r ) && ( g == in.g ) && ( b == in.b );
}
inline bool operator!=( const RGB888_t& in ) const
{
return ( r != in.r ) || ( g != in.g ) || ( b != in.b );
}
};
struct BGR888_t
{
unsigned char b;
unsigned char g;
unsigned char r;
inline BGR888_t& operator=( const BGRA8888_t& in )
{
r = in.r;
g = in.g;
b = in.b;
return *this;
}
};
// 360 uses this structure for x86 dxt decoding
#if defined( _X360 )
#pragma bitfield_order( push, lsb_to_msb )
#endif
struct BGR565_t
{
unsigned short b : 5; // order of names changes
unsigned short g : 6; // byte order of output to 32 bit
unsigned short r : 5;
inline BGR565_t& operator=( const BGRA8888_t& in )
{
r = in.r >> 3;
g = in.g >> 2;
b = in.b >> 3;
return *this;
}
inline BGR565_t &Set( int red, int green, int blue )
{
r = red >> 3;
g = green >> 2;
b = blue >> 3;
return *this;
}
};
#if defined( _X360 )
#pragma bitfield_order( pop )
#endif
struct BGRA5551_t
{
unsigned short b : 5; // order of names changes
unsigned short g : 5; // byte order of output to 32 bit
unsigned short r : 5;
unsigned short a : 1;
inline BGRA5551_t& operator=( const BGRA8888_t& in )
{
r = in.r >> 3;
g = in.g >> 3;
b = in.b >> 3;
a = in.a >> 7;
return *this;
}
};
struct BGRA4444_t
{
unsigned short b : 4; // order of names changes
unsigned short g : 4; // byte order of output to 32 bit
unsigned short r : 4;
unsigned short a : 4;
inline BGRA4444_t& operator=( const BGRA8888_t& in )
{
r = in.r >> 4;
g = in.g >> 4;
b = in.b >> 4;
a = in.a >> 4;
return *this;
}
};
struct RGBX5551_t
{
unsigned short r : 5;
unsigned short g : 5;
unsigned short b : 5;
unsigned short x : 1;
inline RGBX5551_t& operator=( const BGRA8888_t& in )
{
r = in.r >> 3;
g = in.g >> 3;
b = in.b >> 3;
return *this;
}
};
//-----------------------------------------------------------------------------
// some important constants
//-----------------------------------------------------------------------------
#define ARTWORK_GAMMA ( 2.2f )
#define IMAGE_MAX_DIM ( 2048 )
//-----------------------------------------------------------------------------
// information about each image format
//-----------------------------------------------------------------------------
struct ImageFormatInfo_t
{
const char* m_pName;
int m_NumBytes;
int m_NumRedBits;
int m_NumGreeBits;
int m_NumBlueBits;
int m_NumAlphaBits;
bool m_IsCompressed;
};
//-----------------------------------------------------------------------------
// Various methods related to pixelmaps and color formats
//-----------------------------------------------------------------------------
namespace ImageLoader
{
bool GetInfo( const char *fileName, int *width, int *height, enum ImageFormat *imageFormat, float *sourceGamma );
int GetMemRequired( int width, int height, int depth, ImageFormat imageFormat, bool mipmap );
int GetMipMapLevelByteOffset( int width, int height, enum ImageFormat imageFormat, int skipMipLevels );
void GetMipMapLevelDimensions( int *width, int *height, int skipMipLevels );
int GetNumMipMapLevels( int width, int height, int depth = 1 );
bool Load( unsigned char *imageData, const char *fileName, int width, int height, enum ImageFormat imageFormat, float targetGamma, bool mipmap );
bool Load( unsigned char *imageData, FILE *fp, int width, int height,
enum ImageFormat imageFormat, float targetGamma, bool mipmap );
// convert from any image format to any other image format.
// return false if the conversion cannot be performed.
// Strides denote the number of bytes per each line,
// by default assumes width * # of bytes per pixel
bool ConvertImageFormat( const unsigned char *src, enum ImageFormat srcImageFormat,
unsigned char *dst, enum ImageFormat dstImageFormat,
int width, int height, int srcStride = 0, int dstStride = 0 );
// must be used in conjunction with ConvertImageFormat() to pre-swap and post-swap
void PreConvertSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width = 0, int stride = 0 );
void PostConvertSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width = 0, int stride = 0 );
void ByteSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width = 0, int stride = 0 );
bool IsFormatValidForConversion( ImageFormat fmt );
//-----------------------------------------------------------------------------
// convert back and forth from D3D format to ImageFormat, regardless of
// whether it's supported or not
//-----------------------------------------------------------------------------
ImageFormat D3DFormatToImageFormat( D3DFORMAT format );
D3DFORMAT ImageFormatToD3DFormat( ImageFormat format );
// Flags for ResampleRGBA8888
enum
{
RESAMPLE_NORMALMAP = 0x1,
RESAMPLE_ALPHATEST = 0x2,
RESAMPLE_NICE_FILTER = 0x4,
RESAMPLE_CLAMPS = 0x8,
RESAMPLE_CLAMPT = 0x10,
RESAMPLE_CLAMPU = 0x20,
};
struct ResampleInfo_t
{
ResampleInfo_t() : m_nFlags(0), m_flAlphaThreshhold(0.4f), m_flAlphaHiFreqThreshhold(0.4f), m_nSrcDepth(1), m_nDestDepth(1)
{
m_flColorScale[0] = 1.0f, m_flColorScale[1] = 1.0f, m_flColorScale[2] = 1.0f, m_flColorScale[3] = 1.0f;
m_flColorGoal[0] = 0.0f, m_flColorGoal[1] = 0.0f, m_flColorGoal[2] = 0.0f, m_flColorGoal[3] = 0.0f;
}
unsigned char *m_pSrc;
unsigned char *m_pDest;
int m_nSrcWidth;
int m_nSrcHeight;
int m_nSrcDepth;
int m_nDestWidth;
int m_nDestHeight;
int m_nDestDepth;
float m_flSrcGamma;
float m_flDestGamma;
float m_flColorScale[4]; // Color scale factors RGBA
float m_flColorGoal[4]; // Color goal values RGBA DestColor = ColorGoal + scale * (SrcColor - ColorGoal)
float m_flAlphaThreshhold;
float m_flAlphaHiFreqThreshhold;
int m_nFlags;
};
bool ResampleRGBA8888( const ResampleInfo_t &info );
bool ResampleRGBA16161616( const ResampleInfo_t &info );
bool ResampleRGB323232F( const ResampleInfo_t &info );
void ConvertNormalMapRGBA8888ToDUDVMapUVLX8888( const unsigned char *src, int width, int height,
unsigned char *dst_ );
void ConvertNormalMapRGBA8888ToDUDVMapUVWQ8888( const unsigned char *src, int width, int height,
unsigned char *dst_ );
void ConvertNormalMapRGBA8888ToDUDVMapUV88( const unsigned char *src, int width, int height,
unsigned char *dst_ );
void ConvertIA88ImageToNormalMapRGBA8888( const unsigned char *src, int width,
int height, unsigned char *dst,
float bumpScale );
void NormalizeNormalMapRGBA8888( unsigned char *src, int numTexels );
//-----------------------------------------------------------------------------
// Gamma correction
//-----------------------------------------------------------------------------
void GammaCorrectRGBA8888( unsigned char *src, unsigned char* dst,
int width, int height, int depth, float srcGamma, float dstGamma );
//-----------------------------------------------------------------------------
// Makes a gamma table
//-----------------------------------------------------------------------------
void ConstructGammaTable( unsigned char* pTable, float srcGamma, float dstGamma );
//-----------------------------------------------------------------------------
// Gamma corrects using a previously constructed gamma table
//-----------------------------------------------------------------------------
void GammaCorrectRGBA8888( unsigned char* pSrc, unsigned char* pDst,
int width, int height, int depth, unsigned char* pGammaTable );
//-----------------------------------------------------------------------------
// Generates a number of mipmap levels
//-----------------------------------------------------------------------------
void GenerateMipmapLevels( unsigned char* pSrc, unsigned char* pDst, int width,
int height, int depth, ImageFormat imageFormat, float srcGamma, float dstGamma,
int numLevels = 0 );
//-----------------------------------------------------------------------------
// operations on square images (src and dst can be the same)
//-----------------------------------------------------------------------------
bool RotateImageLeft( const unsigned char *src, unsigned char *dst,
int widthHeight, ImageFormat imageFormat );
bool RotateImage180( const unsigned char *src, unsigned char *dst,
int widthHeight, ImageFormat imageFormat );
bool FlipImageVertically( void *pSrc, void *pDst, int nWidth, int nHeight, ImageFormat imageFormat, int nDstStride = 0 );
bool FlipImageHorizontally( void *pSrc, void *pDst, int nWidth, int nHeight, ImageFormat imageFormat, int nDstStride = 0 );
bool SwapAxes( unsigned char *src,
int widthHeight, ImageFormat imageFormat );
//-----------------------------------------------------------------------------
// Returns info about each image format
//-----------------------------------------------------------------------------
ImageFormatInfo_t const& ImageFormatInfo( ImageFormat fmt );
//-----------------------------------------------------------------------------
// Gets the name of the image format
//-----------------------------------------------------------------------------
inline char const* GetName( ImageFormat fmt )
{
return ImageFormatInfo(fmt).m_pName;
}
//-----------------------------------------------------------------------------
// Gets the size of the image format in bytes
//-----------------------------------------------------------------------------
inline int SizeInBytes( ImageFormat fmt )
{
return ImageFormatInfo(fmt).m_NumBytes;
}
//-----------------------------------------------------------------------------
// Does the image format support transparency?
//-----------------------------------------------------------------------------
inline bool IsTransparent( ImageFormat fmt )
{
return ImageFormatInfo(fmt).m_NumAlphaBits > 0;
}
//-----------------------------------------------------------------------------
// Is the image format compressed?
//-----------------------------------------------------------------------------
inline bool IsCompressed( ImageFormat fmt )
{
return ImageFormatInfo(fmt).m_IsCompressed;
}
//-----------------------------------------------------------------------------
// Is any channel > 8 bits?
//-----------------------------------------------------------------------------
inline bool HasChannelLargerThan8Bits( ImageFormat fmt )
{
ImageFormatInfo_t info = ImageFormatInfo(fmt);
return ( info.m_NumRedBits > 8 || info.m_NumGreeBits > 8 || info.m_NumBlueBits > 8 || info.m_NumAlphaBits > 8 );
}
} // end namespace ImageLoader
#endif // IMAGEFORMAT_H

105
public/bitmap/psd.h Normal file
View File

@ -0,0 +1,105 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Methods relating to saving + loading PSD files (photoshop)
//
// $NoKeywords: $
//===========================================================================//
#ifndef PSD_H
#define PSD_H
#ifdef _WIN32
#pragma once
#endif
#include "bitmap/imageformat.h" //ImageFormat enum definition
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CUtlBuffer;
struct Bitmap_t;
class PSDImageResources
{
public:
enum Resource {
eResFileInfo = 0x0404
};
struct ResElement {
Resource m_eType;
// unsigned char m_pReserved[4];
unsigned short m_numBytes;
unsigned char const *m_pvData;
};
public:
explicit PSDImageResources( unsigned int numBytes, unsigned char const *pvBuffer ) : m_numBytes( numBytes ), m_pvBuffer( pvBuffer ) {}
public:
ResElement FindElement( Resource eType ) const;
protected:
unsigned int m_numBytes;
unsigned char const * m_pvBuffer;
};
class PSDResFileInfo
{
public:
enum ResFileInfo {
eTitle = 0x05,
eAuthor = 0x50,
eAuthorTitle = 0x55,
eDescription = 0x78,
eDescriptionWriter = 0x7A,
eKeywords = 0x19,
eCopyrightNotice = 0x74
};
struct ResFileInfoElement {
ResFileInfo m_eType;
unsigned short m_numBytes;
unsigned char const *m_pvData;
};
public:
explicit PSDResFileInfo( PSDImageResources::ResElement res ) : m_res( res ) {}
public:
ResFileInfoElement FindElement( ResFileInfo eType ) const;
protected:
PSDImageResources::ResElement m_res;
};
//-----------------------------------------------------------------------------
// Is a file a PSD file?
//-----------------------------------------------------------------------------
bool IsPSDFile( const char *pFileName, const char *pPathID );
bool IsPSDFile( CUtlBuffer &buf );
//-----------------------------------------------------------------------------
// Returns information about the PSD file
//-----------------------------------------------------------------------------
bool PSDGetInfo( const char *pFileName, const char *pPathID, int *pWidth, int *pHeight, ImageFormat *pImageFormat, float *pSourceGamma );
bool PSDGetInfo( CUtlBuffer &buf, int *pWidth, int *pHeight, ImageFormat *pImageFormat, float *pSourceGamma );
//-----------------------------------------------------------------------------
// Get PSD file image resources, pointers refer into the utlbuffer
//-----------------------------------------------------------------------------
PSDImageResources PSDGetImageResources( CUtlBuffer &buf );
//-----------------------------------------------------------------------------
// Reads the PSD file into the specified buffer
//-----------------------------------------------------------------------------
bool PSDReadFileRGBA8888( CUtlBuffer &buf, Bitmap_t &bitmap );
bool PSDReadFileRGBA8888( const char *pFileName, const char *pPathID, Bitmap_t &bitmap );
#endif // PSD_H

45
public/bitmap/tgaloader.h Normal file
View File

@ -0,0 +1,45 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
#ifndef TGALOADER_H
#define TGALOADER_H
#ifdef _WIN32
#pragma once
#endif
#include "bitmap/imageformat.h"
#include "tier1/utlmemory.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CUtlBuffer;
namespace TGALoader
{
int TGAHeaderSize();
bool GetInfo( const char *fileName, int *width, int *height, ImageFormat *imageFormat, float *sourceGamma );
bool GetInfo( CUtlBuffer &buf, int *width, int *height, ImageFormat *imageFormat, float *sourceGamma );
bool Load( unsigned char *imageData, const char *fileName, int width, int height,
ImageFormat imageFormat, float targetGamma, bool mipmap );
bool Load( unsigned char *imageData, CUtlBuffer &buf, int width, int height,
ImageFormat imageFormat, float targetGamma, bool mipmap );
bool LoadRGBA8888( const char *pFileName, CUtlMemory<unsigned char> &outputData, int &outWidth, int &outHeight );
bool LoadRGBA8888( CUtlBuffer &buf, CUtlMemory<unsigned char> &outputData, int &outWidth, int &outHeight );
} // end namespace TGALoader
#endif // TGALOADER_H

40
public/bitmap/tgawriter.h Normal file
View File

@ -0,0 +1,40 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef TGAWRITER_H
#define TGAWRITER_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/interface.h"
#include "bitmap/imageformat.h" //ImageFormat enum definition
class CUtlBuffer;
namespace TGAWriter
{
bool WriteToBuffer( unsigned char *pImageData, CUtlBuffer &buffer, int width, int height,
ImageFormat srcFormat, ImageFormat dstFormat );
// write out a simple tga file from a memory buffer.
bool WriteTGAFile( const char *fileName, int width, int height, enum ImageFormat srcFormat, uint8 const *srcData, int nStride );
// A pair of routines for writing to files without allocating any memory in the TGA writer
// Useful for very large files such as posters, which are rendered as sub-rects anyway
bool WriteDummyFileNoAlloc( const char *fileName, int width, int height, ImageFormat dstFormat );
bool WriteRectNoAlloc( unsigned char *pImageData, const char *fileName, int nXOrigin, int nYOrigin, int width, int height, int nStride, ImageFormat srcFormat );
} // end namespace TGAWriter
#endif // TGAWRITER_H

1442
public/bitvec.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,150 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#if defined(_WIN32) && !defined(_X360)
#include <winsock.h>
#elif POSIX
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#define closesocket close
#endif
#include "blockingudpsocket.h"
#include "tier0/vcrmode.h"
class CBlockingUDPSocket::CImpl
{
public:
struct sockaddr_in m_SocketIP;
fd_set m_FDSet;
};
CBlockingUDPSocket::CBlockingUDPSocket() :
m_cserIP(),
m_Socket( 0 ),
m_pImpl( new CImpl )
{
CreateSocket();
}
CBlockingUDPSocket::~CBlockingUDPSocket()
{
delete m_pImpl;
closesocket( static_cast<unsigned int>( m_Socket ));
}
bool CBlockingUDPSocket::CreateSocket (void)
{
struct sockaddr_in address;
m_Socket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( m_Socket == INVALID_SOCKET )
{
return false;
}
address = m_pImpl->m_SocketIP;
if ( SOCKET_ERROR == bind( m_Socket, ( struct sockaddr * )&address, sizeof( address ) ) )
{
return false;
}
#ifdef _WIN32
if ( m_pImpl->m_SocketIP.sin_addr.S_un.S_addr == INADDR_ANY )
{
m_pImpl->m_SocketIP.sin_addr.S_un.S_addr = 0L;
}
#elif POSIX
if ( m_pImpl->m_SocketIP.sin_addr.s_addr == INADDR_ANY )
{
m_pImpl->m_SocketIP.sin_addr.s_addr = 0L;
}
#endif
return true;
}
bool CBlockingUDPSocket::WaitForMessage( float timeOutInSeconds )
{
struct timeval tv;
FD_ZERO( &m_pImpl->m_FDSet );
FD_SET( m_Socket, &m_pImpl->m_FDSet );//lint !e717
tv.tv_sec = (int)timeOutInSeconds;
float remainder = timeOutInSeconds - (int)timeOutInSeconds;
tv.tv_usec = (int)( remainder * 1000000 + 0.5f ); /* micro seconds */
if ( SOCKET_ERROR == select( ( int )m_Socket + 1, &m_pImpl->m_FDSet, NULL, NULL, &tv ) )
{
return false;
}
if ( FD_ISSET( m_Socket, &m_pImpl->m_FDSet) )
{
return true;
}
// Timed out
return false;
}
unsigned int CBlockingUDPSocket::ReceiveSocketMessage( struct sockaddr_in *packet_from, unsigned char *buf, size_t bufsize )
{
memset( packet_from, 0, sizeof( *packet_from ) );
struct sockaddr fromaddress;
int fromlen = sizeof( fromaddress );
int packet_length = VCRHook_recvfrom
(
m_Socket,
(char *)buf,
(int)bufsize,
0,
&fromaddress,
&fromlen
);
if ( SOCKET_ERROR == packet_length )
{
return 0;
}
// In case it's parsed as a string
buf[ packet_length ] = 0;
// Copy over the receive address
*packet_from = *( struct sockaddr_in * )&fromaddress;
return ( unsigned int )packet_length;
}
bool CBlockingUDPSocket::SendSocketMessage( const struct sockaddr_in & rRecipient, const unsigned char *buf, size_t bufsize )
{
// Send data
int bytesSent = sendto
(
m_Socket,
(const char *)buf,
(int)bufsize,
0,
reinterpret_cast< const sockaddr * >( &rRecipient ),
sizeof( rRecipient )
);
if ( SOCKET_ERROR == bytesSent )
{
return false;
}
return true;
}

View File

@ -0,0 +1,39 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef BLOCKINGUDPSOCKET_H
#define BLOCKINGUDPSOCKET_H
#ifdef _WIN32
#pragma once
#endif
#include "netadr.h"
class CBlockingUDPSocket
{
public:
explicit CBlockingUDPSocket();
virtual ~CBlockingUDPSocket();
bool WaitForMessage( float timeOutInSeconds );
unsigned int ReceiveSocketMessage( struct sockaddr_in *packet_from, unsigned char *buf, size_t bufsize );
bool SendSocketMessage( const struct sockaddr_in& rRecipient, const unsigned char *buf, size_t bufsize );
bool IsValid() const { return m_Socket != 0; }
protected:
bool CreateSocket (void);
class CImpl;
CImpl *m_pImpl;
netadr_t m_cserIP;
unsigned int m_Socket;
};
#endif // BLOCKINGUDPSOCKET_H

34
public/bone_accessor.cpp Normal file
View File

@ -0,0 +1,34 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "bone_accessor.h"
#if defined( CLIENT_DLL ) && defined( _DEBUG )
void CBoneAccessor::SanityCheckBone( int iBone, bool bReadable ) const
{
if ( m_pAnimating )
{
CStudioHdr *pHdr = m_pAnimating->GetModelPtr();
if ( pHdr )
{
mstudiobone_t *pBone = pHdr->pBone( iBone );
if ( bReadable )
{
AssertOnce( pBone->flags & m_ReadableBones );
}
else
{
AssertOnce( pBone->flags & m_WritableBones );
}
}
}
}
#endif

131
public/bone_accessor.h Normal file
View File

@ -0,0 +1,131 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef BONE_ACCESSOR_H
#define BONE_ACCESSOR_H
#ifdef _WIN32
#pragma once
#endif
#include "studio.h"
class C_BaseAnimating;
class CBoneAccessor
{
public:
CBoneAccessor();
CBoneAccessor( matrix3x4_t *pBones ); // This can be used to allow access to all bones.
// Initialize.
#if defined( CLIENT_DLL )
void Init( const C_BaseAnimating *pAnimating, matrix3x4_t *pBones );
#endif
int GetReadableBones();
void SetReadableBones( int flags );
int GetWritableBones();
void SetWritableBones( int flags );
// Get bones for read or write access.
const matrix3x4_t& GetBone( int iBone ) const;
const matrix3x4_t& operator[]( int iBone ) const;
matrix3x4_t& GetBoneForWrite( int iBone );
matrix3x4_t *GetBoneArrayForWrite( ) const;
private:
#if defined( CLIENT_DLL ) && defined( _DEBUG )
void SanityCheckBone( int iBone, bool bReadable ) const;
#endif
// Only used in the client DLL for debug verification.
const C_BaseAnimating *m_pAnimating;
matrix3x4_t *m_pBones;
int m_ReadableBones; // Which bones can be read.
int m_WritableBones; // Which bones can be written.
};
inline CBoneAccessor::CBoneAccessor()
{
m_pAnimating = NULL;
m_pBones = NULL;
m_ReadableBones = m_WritableBones = 0;
}
inline CBoneAccessor::CBoneAccessor( matrix3x4_t *pBones )
{
m_pAnimating = NULL;
m_pBones = pBones;
}
#if defined( CLIENT_DLL )
inline void CBoneAccessor::Init( const C_BaseAnimating *pAnimating, matrix3x4_t *pBones )
{
m_pAnimating = pAnimating;
m_pBones = pBones;
}
#endif
inline int CBoneAccessor::GetReadableBones()
{
return m_ReadableBones;
}
inline void CBoneAccessor::SetReadableBones( int flags )
{
m_ReadableBones = flags;
}
inline int CBoneAccessor::GetWritableBones()
{
return m_WritableBones;
}
inline void CBoneAccessor::SetWritableBones( int flags )
{
m_WritableBones = flags;
}
inline const matrix3x4_t& CBoneAccessor::GetBone( int iBone ) const
{
#if defined( CLIENT_DLL ) && defined( _DEBUG )
SanityCheckBone( iBone, true );
#endif
return m_pBones[iBone];
}
inline const matrix3x4_t& CBoneAccessor::operator[]( int iBone ) const
{
#if defined( CLIENT_DLL ) && defined( _DEBUG )
SanityCheckBone( iBone, true );
#endif
return m_pBones[iBone];
}
inline matrix3x4_t& CBoneAccessor::GetBoneForWrite( int iBone )
{
#if defined( CLIENT_DLL ) && defined( _DEBUG )
SanityCheckBone( iBone, false );
#endif
return m_pBones[iBone];
}
inline matrix3x4_t *CBoneAccessor::GetBoneArrayForWrite( void ) const
{
return m_pBones;
}
#endif // BONE_ACCESSOR_H

5948
public/bone_setup.cpp Normal file

File diff suppressed because it is too large Load Diff

447
public/bone_setup.h Normal file
View File

@ -0,0 +1,447 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BONE_SETUP_H
#define BONE_SETUP_H
#ifdef _WIN32
#pragma once
#endif
#include "studio.h"
#include "cmodel.h"
#include "bitvec.h"
class CBoneToWorld;
class CIKContext;
class CBoneAccessor;
class IPoseDebugger;
// This provides access to networked arrays, so if this code actually changes a value,
// the entity is marked as changed.
abstract_class IParameterAccess
{
public:
virtual float GetParameter( int iParam ) = 0;
virtual void SetParameter( int iParam, float flValue ) = 0;
};
class CBoneBitList : public CBitVec<MAXSTUDIOBONES>
{
public:
inline void MarkBone(int iBone)
{
Set(iBone);
}
inline bool IsBoneMarked(int iBone)
{
return Get(iBone) != 0 ? true : false;
}
};
class CBoneSetup;
class IBoneSetup
{
public:
IBoneSetup( const CStudioHdr *pStudioHdr, int boneMask, const float poseParameter[], IPoseDebugger *pPoseDebugger = NULL );
~IBoneSetup( void );
void InitPose( Vector pos[], Quaternion[] );
void AccumulatePose( Vector pos[], Quaternion q[], int sequence, float cycle, float flWeight, float flTime, CIKContext *pIKContext );
void CalcAutoplaySequences( Vector pos[], Quaternion q[], float flRealTime, CIKContext *pIKContext );
void CalcBoneAdj( Vector pos[], Quaternion q[], const float controllers[] );
CStudioHdr *GetStudioHdr();
private:
CBoneSetup *m_pBoneSetup;
};
//-----------------------------------------------------------------------------
// Purpose: blends together all the bones from two p:q lists
//
// p1 = p1 * (1 - s) + p2 * s
// q1 = q1 * (1 - s) + q2 * s
//-----------------------------------------------------------------------------
void SlerpBones(
const CStudioHdr *pStudioHdr,
Quaternion q1[MAXSTUDIOBONES],
Vector pos1[MAXSTUDIOBONES],
mstudioseqdesc_t &seqdesc, // source of q2 and pos2
int sequence,
const Quaternion q2[MAXSTUDIOBONES],
const Vector pos2[MAXSTUDIOBONES],
float s,
int boneMask
);
// Given two samples of a bone separated in time by dt,
// compute the velocity and angular velocity of that bone
void CalcBoneDerivatives( Vector &velocity, AngularImpulse &angVel, const matrix3x4_t &prev, const matrix3x4_t &current, float dt );
// Give a derivative of a bone, compute the velocity & angular velocity of that bone
void CalcBoneVelocityFromDerivative( const QAngle &vecAngles, Vector &velocity, AngularImpulse &angVel, const matrix3x4_t &current );
// This function sets up the local transform for a single frame of animation. It doesn't handle
// pose parameters or interpolation between frames.
void SetupSingleBoneMatrix(
CStudioHdr *pOwnerHdr,
int nSequence,
int iFrame,
int iBone,
matrix3x4_t &mBoneLocal );
// Purpose: build boneToWorld transforms for a specific bone
void BuildBoneChain(
const CStudioHdr *pStudioHdr,
const matrix3x4_t &rootxform,
const Vector pos[],
const Quaternion q[],
int iBone,
matrix3x4_t *pBoneToWorld );
void BuildBoneChain(
const CStudioHdr *pStudioHdr,
const matrix3x4_t &rootxform,
const Vector pos[],
const Quaternion q[],
int iBone,
matrix3x4_t *pBoneToWorld,
CBoneBitList &boneComputed );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
// ik info
class CIKTarget
{
public:
void SetOwner( int entindex, const Vector &pos, const QAngle &angles );
void ClearOwner( void );
int GetOwner( void );
void UpdateOwner( int entindex, const Vector &pos, const QAngle &angles );
void SetPos( const Vector &pos );
void SetAngles( const QAngle &angles );
void SetQuaternion( const Quaternion &q );
void SetNormal( const Vector &normal );
void SetPosWithNormalOffset( const Vector &pos, const Vector &normal );
void SetOnWorld( bool bOnWorld = true );
bool IsActive( void );
void IKFailed( void );
int chain;
int type;
void MoveReferenceFrame( Vector &deltaPos, QAngle &deltaAngles );
// accumulated offset from ideal footplant location
public:
struct x2 {
char *pAttachmentName;
Vector pos;
Quaternion q;
} offset;
private:
struct x3 {
Vector pos;
Quaternion q;
} ideal;
public:
struct x4 {
float latched;
float release;
float height;
float floor;
float radius;
float flTime;
float flWeight;
Vector pos;
Quaternion q;
bool onWorld;
} est; // estimate contact position
struct x5 {
float hipToFoot; // distance from hip
float hipToKnee; // distance from hip to knee
float kneeToFoot; // distance from knee to foot
Vector hip; // location of hip
Vector closest; // closest valid location from hip to foot that the foot can move to
Vector knee; // pre-ik location of knee
Vector farthest; // farthest valid location from hip to foot that the foot can move to
Vector lowest; // lowest position directly below hip that the foot can drop to
} trace;
private:
// internally latched footset, position
struct x1 {
// matrix3x4_t worldTarget;
bool bNeedsLatch;
bool bHasLatch;
float influence;
int iFramecounter;
int owner;
Vector absOrigin;
QAngle absAngles;
Vector pos;
Quaternion q;
Vector deltaPos; // acculated error
Quaternion deltaQ;
Vector debouncePos;
Quaternion debounceQ;
} latched;
struct x6 {
float flTime; // time last error was detected
float flErrorTime;
float ramp;
bool bInError;
} error;
friend class CIKContext;
};
struct ikchainresult_t
{
// accumulated offset from ideal footplant location
int target;
Vector pos;
Quaternion q;
float flWeight;
};
struct ikcontextikrule_t
{
int index;
int type;
int chain;
int bone;
int slot; // iktarget slot. Usually same as chain.
float height;
float radius;
float floor;
Vector pos;
Quaternion q;
float start; // beginning of influence
float peak; // start of full influence
float tail; // end of full influence
float end; // end of all influence
float top;
float drop;
float commit; // frame footstep target should be committed
float release; // frame ankle should end rotation from latched orientation
float flWeight; // processed version of start-end cycle
float flRuleWeight; // blending weight
float latched; // does the IK rule use a latched value?
char *szLabel;
Vector kneeDir;
Vector kneePos;
ikcontextikrule_t() {}
private:
// No copy constructors allowed
ikcontextikrule_t(const ikcontextikrule_t& vOther);
};
void Studio_AlignIKMatrix( matrix3x4_t &mMat, const Vector &vAlignTo );
bool Studio_SolveIK( int iThigh, int iKnee, int iFoot, Vector &targetFoot, matrix3x4_t* pBoneToWorld );
bool Studio_SolveIK( int iThigh, int iKnee, int iFoot, Vector &targetFoot, Vector &targetKneePos, Vector &targetKneeDir, matrix3x4_t* pBoneToWorld );
class CIKContext
{
public:
CIKContext( );
void Init( const CStudioHdr *pStudioHdr, const QAngle &angles, const Vector &pos, float flTime, int iFramecounter, int boneMask );
void AddDependencies( mstudioseqdesc_t &seqdesc, int iSequence, float flCycle, const float poseParameters[], float flWeight = 1.0f );
void ClearTargets( void );
void UpdateTargets( Vector pos[], Quaternion q[], matrix3x4_t boneToWorld[], CBoneBitList &boneComputed );
void AutoIKRelease( void );
void SolveDependencies( Vector pos[], Quaternion q[], matrix3x4_t boneToWorld[], CBoneBitList &boneComputed );
void AddAutoplayLocks( Vector pos[], Quaternion q[] );
void SolveAutoplayLocks( Vector pos[], Quaternion q[] );
void AddSequenceLocks( mstudioseqdesc_t &SeqDesc, Vector pos[], Quaternion q[] );
void SolveSequenceLocks( mstudioseqdesc_t &SeqDesc, Vector pos[], Quaternion q[] );
void AddAllLocks( Vector pos[], Quaternion q[] );
void SolveAllLocks( Vector pos[], Quaternion q[] );
void SolveLock( const mstudioiklock_t *plock, int i, Vector pos[], Quaternion q[], matrix3x4_t boneToWorld[], CBoneBitList &boneComputed );
CUtlVectorFixed< CIKTarget, 12 > m_target;
private:
CStudioHdr const *m_pStudioHdr;
bool Estimate( int iSequence, float flCycle, int iTarget, const float poseParameter[], float flWeight = 1.0f );
void BuildBoneChain( const Vector pos[], const Quaternion q[], int iBone, matrix3x4_t *pBoneToWorld, CBoneBitList &boneComputed );
// virtual IK rules, filtered and combined from each sequence
CUtlVector< CUtlVector< ikcontextikrule_t > > m_ikChainRule;
CUtlVector< ikcontextikrule_t > m_ikLock;
matrix3x4_t m_rootxform;
int m_iFramecounter;
float m_flTime;
int m_boneMask;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
// replaces the bonetoworld transforms for all bones that are procedural
bool CalcProceduralBone(
const CStudioHdr *pStudioHdr,
int iBone,
CBoneAccessor &bonetoworld
);
void Studio_BuildMatrices(
const CStudioHdr *pStudioHdr,
const QAngle& angles,
const Vector& origin,
const Vector pos[],
const Quaternion q[],
int iBone,
float flScale,
matrix3x4_t bonetoworld[MAXSTUDIOBONES],
int boneMask
);
// Get a bone->bone relative transform
void Studio_CalcBoneToBoneTransform( const CStudioHdr *pStudioHdr, int inputBoneIndex, int outputBoneIndex, matrix3x4_t &matrixOut );
// Given a bone rotation value, figures out the value you need to give to the controller
// to have the bone at that value.
// [in] flValue = the desired bone rotation value
// [out] ctlValue = the (0-1) value to set the controller t.
// return value = flValue, unwrapped to lie between the controller's start and end.
float Studio_SetController( const CStudioHdr *pStudioHdr, int iController, float flValue, float &ctlValue );
// Given a 0-1 controller value, maps it into the controller's start and end and returns the bone rotation angle.
// [in] ctlValue = value in controller space (0-1).
// return value = value in bone space
float Studio_GetController( const CStudioHdr *pStudioHdr, int iController, float ctlValue );
void Studio_CalcDefaultPoseParameters( const CStudioHdr *pStudioHdr, float flPoseParameter[MAXSTUDIOPOSEPARAM], int nCount );
float Studio_GetPoseParameter( const CStudioHdr *pStudioHdr, int iParameter, float ctlValue );
float Studio_SetPoseParameter( const CStudioHdr *pStudioHdr, int iParameter, float flValue, float &ctlValue );
// converts a global 0..1 pose parameter into the local sequences blending value
void Studio_LocalPoseParameter( const CStudioHdr *pStudioHdr, const float poseParameter[], mstudioseqdesc_t &seqdesc, int iSequence, int iLocalIndex, float &flSetting, int &index );
void Studio_SeqAnims( const CStudioHdr *pStudioHdr, mstudioseqdesc_t &seqdesc, int iSequence, const float poseParameter[], mstudioanimdesc_t *panim[4], float *weight );
int Studio_MaxFrame( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[] );
float Studio_FPS( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[] );
float Studio_CPS( const CStudioHdr *pStudioHdr, mstudioseqdesc_t &seqdesc, int iSequence, const float poseParameter[] );
float Studio_Duration( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[] );
void Studio_MovementRate( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[], Vector *pVec );
// void Studio_Movement( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[], Vector *pVec );
//void Studio_AnimPosition( mstudioanimdesc_t *panim, float flCycle, Vector &vecPos, Vector &vecAngle );
//void Studio_AnimVelocity( mstudioanimdesc_t *panim, float flCycle, Vector &vecVelocity );
//float Studio_FindAnimDistance( mstudioanimdesc_t *panim, float flDist );
bool Studio_AnimMovement( mstudioanimdesc_t *panim, float flCycleFrom, float flCycleTo, Vector &deltaPos, QAngle &deltaAngle );
bool Studio_SeqMovement( const CStudioHdr *pStudioHdr, int iSequence, float flCycleFrom, float flCycleTo, const float poseParameter[], Vector &deltaMovement, QAngle &deltaAngle );
bool Studio_SeqVelocity( const CStudioHdr *pStudioHdr, int iSequence, float flCycle, const float poseParameter[], Vector &vecVelocity );
float Studio_FindSeqDistance( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[], float flDist );
float Studio_FindSeqVelocity( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[], float flVelocity );
int Studio_FindAttachment( const CStudioHdr *pStudioHdr, const char *pAttachmentName );
int Studio_FindRandomAttachment( const CStudioHdr *pStudioHdr, const char *pAttachmentName );
int Studio_BoneIndexByName( const CStudioHdr *pStudioHdr, const char *pName );
const char *Studio_GetDefaultSurfaceProps( CStudioHdr *pstudiohdr );
float Studio_GetMass( CStudioHdr *pstudiohdr );
const char *Studio_GetKeyValueText( const CStudioHdr *pStudioHdr, int iSequence );
FORWARD_DECLARE_HANDLE( memhandle_t );
struct bonecacheparams_t
{
CStudioHdr *pStudioHdr;
matrix3x4_t *pBoneToWorld;
float curtime;
int boneMask;
};
class CBoneCache
{
public:
// you must implement these static functions for the ResourceManager
// -----------------------------------------------------------
static CBoneCache *CreateResource( const bonecacheparams_t &params );
static unsigned int EstimatedSize( const bonecacheparams_t &params );
// -----------------------------------------------------------
// member functions that must be present for the ResourceManager
void DestroyResource();
CBoneCache *GetData() { return this; }
unsigned int Size() { return m_size; }
// -----------------------------------------------------------
CBoneCache();
// was constructor, but placement new is messy wrt memdebug - so cast & init instead
void Init( const bonecacheparams_t &params, unsigned int size, short *pStudioToCached, short *pCachedToStudio, int cachedBoneCount );
void UpdateBones( const matrix3x4_t *pBoneToWorld, int numbones, float curtime );
matrix3x4_t *GetCachedBone( int studioIndex );
void ReadCachedBones( matrix3x4_t *pBoneToWorld );
void ReadCachedBonePointers( matrix3x4_t **bones, int numbones );
bool IsValid( float curtime, float dt = 0.1f );
public:
float m_timeValid;
int m_boneMask;
private:
matrix3x4_t *BoneArray();
short *StudioToCached();
short *CachedToStudio();
unsigned int m_size;
unsigned short m_cachedBoneCount;
unsigned short m_matrixOffset;
unsigned short m_cachedToStudioOffset;
unsigned short m_boneOutOffset;
};
CBoneCache *Studio_GetBoneCache( memhandle_t cacheHandle );
memhandle_t Studio_CreateBoneCache( bonecacheparams_t &params );
void Studio_DestroyBoneCache( memhandle_t cacheHandle );
void Studio_InvalidateBoneCache( memhandle_t cacheHandle );
// Given a ray, trace for an intersection with this studiomodel. Get the array of bones from StudioSetupHitboxBones
bool TraceToStudio( class IPhysicsSurfaceProps *pProps, const Ray_t& ray, CStudioHdr *pStudioHdr, mstudiohitboxset_t *set, matrix3x4_t **hitboxbones, int fContentsMask, const Vector &vecOrigin, float flScale, trace_t &trace );
void QuaternionSM( float s, const Quaternion &p, const Quaternion &q, Quaternion &qt );
void QuaternionMA( const Quaternion &p, float s, const Quaternion &q, Quaternion &qt );
bool Studio_PrefetchSequence( const CStudioHdr *pStudioHdr, int iSequence );
#endif // BONE_SETUP_H

1154
public/bspfile.h Normal file

File diff suppressed because it is too large Load Diff

149
public/bspflags.h Normal file
View File

@ -0,0 +1,149 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef BSPFLAGS_H
#define BSPFLAGS_H
#ifdef _WIN32
#pragma once
#endif
// contents flags are seperate bits
// a given brush can contribute multiple content bits
// multiple brushes can be in a single leaf
// these definitions also need to be in q_shared.h!
// lower bits are stronger, and will eat weaker brushes completely
#define CONTENTS_EMPTY 0 // No contents
#define CONTENTS_SOLID 0x1 // an eye is never valid in a solid
#define CONTENTS_WINDOW 0x2 // translucent, but not watery (glass)
#define CONTENTS_AUX 0x4
#define CONTENTS_GRATE 0x8 // alpha-tested "grate" textures. Bullets/sight pass through, but solids don't
#define CONTENTS_SLIME 0x10
#define CONTENTS_WATER 0x20
#define CONTENTS_BLOCKLOS 0x40 // block AI line of sight
#define CONTENTS_OPAQUE 0x80 // things that cannot be seen through (may be non-solid though)
#define LAST_VISIBLE_CONTENTS 0x80
#define ALL_VISIBLE_CONTENTS (LAST_VISIBLE_CONTENTS | (LAST_VISIBLE_CONTENTS-1))
#define CONTENTS_TESTFOGVOLUME 0x100
#define CONTENTS_UNUSED 0x200
// unused
// NOTE: If it's visible, grab from the top + update LAST_VISIBLE_CONTENTS
// if not visible, then grab from the bottom.
#define CONTENTS_UNUSED6 0x400
#define CONTENTS_TEAM1 0x800 // per team contents used to differentiate collisions
#define CONTENTS_TEAM2 0x1000 // between players and objects on different teams
// ignore CONTENTS_OPAQUE on surfaces that have SURF_NODRAW
#define CONTENTS_IGNORE_NODRAW_OPAQUE 0x2000
// hits entities which are MOVETYPE_PUSH (doors, plats, etc.)
#define CONTENTS_MOVEABLE 0x4000
// remaining contents are non-visible, and don't eat brushes
#define CONTENTS_AREAPORTAL 0x8000
#define CONTENTS_PLAYERCLIP 0x10000
#define CONTENTS_MONSTERCLIP 0x20000
// currents can be added to any other contents, and may be mixed
#define CONTENTS_CURRENT_0 0x40000
#define CONTENTS_CURRENT_90 0x80000
#define CONTENTS_CURRENT_180 0x100000
#define CONTENTS_CURRENT_270 0x200000
#define CONTENTS_CURRENT_UP 0x400000
#define CONTENTS_CURRENT_DOWN 0x800000
#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity
#define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game
#define CONTENTS_DEBRIS 0x4000000
#define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs
#define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans
#define CONTENTS_LADDER 0x20000000
#define CONTENTS_HITBOX 0x40000000 // use accurate hitboxes on trace
// NOTE: These are stored in a short in the engine now. Don't use more than 16 bits
#define SURF_LIGHT 0x0001 // value will hold the light strength
#define SURF_SKY2D 0x0002 // don't draw, indicates we should skylight + draw 2d sky but not draw the 3D skybox
#define SURF_SKY 0x0004 // don't draw, but add to skybox
#define SURF_WARP 0x0008 // turbulent water warp
#define SURF_TRANS 0x0010
#define SURF_NOPORTAL 0x0020 // the surface can not have a portal placed on it
#define SURF_TRIGGER 0x0040 // FIXME: This is an xbox hack to work around elimination of trigger surfaces, which breaks occluders
#define SURF_NODRAW 0x0080 // don't bother referencing the texture
#define SURF_HINT 0x0100 // make a primary bsp splitter
#define SURF_SKIP 0x0200 // completely ignore, allowing non-closed brushes
#define SURF_NOLIGHT 0x0400 // Don't calculate light
#define SURF_BUMPLIGHT 0x0800 // calculate three lightmaps for the surface for bumpmapping
#define SURF_NOSHADOWS 0x1000 // Don't receive shadows
#define SURF_NODECALS 0x2000 // Don't receive decals
#define SURF_NOCHOP 0x4000 // Don't subdivide patches on this surface
#define SURF_HITBOX 0x8000 // surface is part of a hitbox
// -----------------------------------------------------
// spatial content masks - used for spatial queries (traceline,etc.)
// -----------------------------------------------------
#define MASK_ALL (0xFFFFFFFF)
// everything that is normally solid
#define MASK_SOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE)
// everything that blocks player movement
#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE)
// blocks npc movement
#define MASK_NPCSOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE)
// water physics in these contents
#define MASK_WATER (CONTENTS_WATER|CONTENTS_MOVEABLE|CONTENTS_SLIME)
// everything that blocks lighting
#define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_OPAQUE)
// everything that blocks lighting, but with monsters added.
#define MASK_OPAQUE_AND_NPCS (MASK_OPAQUE|CONTENTS_MONSTER)
// everything that blocks line of sight for AI
#define MASK_BLOCKLOS (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_BLOCKLOS)
// everything that blocks line of sight for AI plus NPCs
#define MASK_BLOCKLOS_AND_NPCS (MASK_BLOCKLOS|CONTENTS_MONSTER)
// everything that blocks line of sight for players
#define MASK_VISIBLE (MASK_OPAQUE|CONTENTS_IGNORE_NODRAW_OPAQUE)
// everything that blocks line of sight for players, but with monsters added.
#define MASK_VISIBLE_AND_NPCS (MASK_OPAQUE_AND_NPCS|CONTENTS_IGNORE_NODRAW_OPAQUE)
// bullets see these as solid
#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_HITBOX)
// non-raycasted weapons see this as solid (includes grates)
#define MASK_SHOT_HULL (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_GRATE)
// hits solids (not grates) and passes through everything else
#define MASK_SHOT_PORTAL (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER)
// everything normally solid, except monsters (world+brush only)
#define MASK_SOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_GRATE)
// everything normally solid for player movement, except monsters (world+brush only)
#define MASK_PLAYERSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_PLAYERCLIP|CONTENTS_GRATE)
// everything normally solid for npc movement, except monsters (world+brush only)
#define MASK_NPCSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE)
// just the world, used for route rebuilding
#define MASK_NPCWORLDSTATIC (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE)
// These are things that can split areaportals
#define MASK_SPLITAREAPORTAL (CONTENTS_WATER|CONTENTS_SLIME)
// UNDONE: This is untested, any moving water
#define MASK_CURRENT (CONTENTS_CURRENT_0|CONTENTS_CURRENT_90|CONTENTS_CURRENT_180|CONTENTS_CURRENT_270|CONTENTS_CURRENT_UP|CONTENTS_CURRENT_DOWN)
// everything that blocks corpse movement
// UNDONE: Not used yet / may be deleted
#define MASK_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_GRATE)
#endif // BSPFLAGS_H

352
public/bsptreedata.cpp Normal file
View File

@ -0,0 +1,352 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Revision: $
// $NoKeywords: $
//
// The BSP tree leaf data system
//
//=============================================================================//
#include "basetypes.h"
#include "bsptreedata.h"
#include "utllinkedlist.h"
#include "utlvector.h"
#include "tier0/dbg.h"
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// The BSP tree leaf data system
//-----------------------------------------------------------------------------
class CBSPTreeData : public IBSPTreeData, public ISpatialLeafEnumerator
{
public:
// constructor, destructor
CBSPTreeData();
virtual ~CBSPTreeData();
// Methods of IBSPTreeData
void Init( ISpatialQuery* pBSPTree );
void Shutdown();
BSPTreeDataHandle_t Insert( int userId, Vector const& mins, Vector const& maxs );
void Remove( BSPTreeDataHandle_t handle );
void ElementMoved( BSPTreeDataHandle_t handle, Vector const& mins, Vector const& maxs );
// Enumerate elements in a particular leaf
bool EnumerateElementsInLeaf( int leaf, IBSPTreeDataEnumerator* pEnum, int context );
// For convenience, enumerates the leaves along a ray, box, etc.
bool EnumerateLeavesAtPoint( Vector const& pt, ISpatialLeafEnumerator* pEnum, int context );
bool EnumerateLeavesInBox( Vector const& mins, Vector const& maxs, ISpatialLeafEnumerator* pEnum, int context );
bool EnumerateLeavesInSphere( Vector const& center, float radius, ISpatialLeafEnumerator* pEnum, int context );
bool EnumerateLeavesAlongRay( Ray_t const& ray, ISpatialLeafEnumerator* pEnum, int context );
// methods of IBSPLeafEnumerator
bool EnumerateLeaf( int leaf, int context );
// Is the element in any leaves at all?
bool IsElementInTree( BSPTreeDataHandle_t handle ) const;
private:
// Creates a new handle
BSPTreeDataHandle_t NewHandle( int userId );
// Adds a handle to the list of handles
void AddHandleToLeaf( int leaf, BSPTreeDataHandle_t handle );
// insert, remove handles from leaves
void InsertIntoTree( BSPTreeDataHandle_t handle, Vector const& mins, Vector const& maxs );
void RemoveFromTree( BSPTreeDataHandle_t handle );
// Returns the number of elements in a leaf
int CountElementsInLeaf( int leaf );
private:
// All the information associated with a particular handle
struct HandleInfo_t
{
int m_UserId; // Client-defined id
unsigned short m_LeafList; // What leafs is it in?
};
// The leaf contains an index into a list of elements
struct Leaf_t
{
unsigned short m_FirstElement;
};
// The handle knows about the leaves it lies in
struct HandleInLeaf_t
{
int m_Leaf; // what leaf is the handle in?
unsigned short m_LeafElementIndex; // what's the m_LeafElements index of the entry?
};
// Stores data associated with each leaf.
CUtlVector< Leaf_t > m_Leaf;
// Stores all unique handles
CUtlLinkedList< HandleInfo_t, unsigned short > m_Handles;
// Maintains the list of all handles in a particular leaf
CUtlLinkedList< BSPTreeDataHandle_t, unsigned short, true > m_LeafElements;
// Maintains the list of all leaves a particular handle spans
CUtlLinkedList< HandleInLeaf_t, unsigned short, true > m_HandleLeafList;
// Interface to BSP tree
ISpatialQuery* m_pBSPTree;
};
//-----------------------------------------------------------------------------
// Class factory
//-----------------------------------------------------------------------------
IBSPTreeData* CreateBSPTreeData()
{
return new CBSPTreeData;
}
void DestroyBSPTreeData( IBSPTreeData* pTreeData )
{
if (pTreeData)
delete pTreeData;
}
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
CBSPTreeData::CBSPTreeData()
{
}
CBSPTreeData::~CBSPTreeData()
{
}
//-----------------------------------------------------------------------------
// Level init, shutdown
//-----------------------------------------------------------------------------
void CBSPTreeData::Init( ISpatialQuery* pBSPTree )
{
Assert( pBSPTree );
m_pBSPTree = pBSPTree;
m_Handles.EnsureCapacity( 1024 );
m_LeafElements.EnsureCapacity( 1024 );
m_HandleLeafList.EnsureCapacity( 1024 );
// Add all the leaves we'll need
int leafCount = m_pBSPTree->LeafCount();
m_Leaf.EnsureCapacity( leafCount );
Leaf_t newLeaf;
newLeaf.m_FirstElement = m_LeafElements.InvalidIndex();
while ( --leafCount >= 0 )
{
m_Leaf.AddToTail( newLeaf );
}
}
void CBSPTreeData::Shutdown()
{
m_Handles.Purge();
m_LeafElements.Purge();
m_HandleLeafList.Purge();
m_Leaf.Purge();
}
//-----------------------------------------------------------------------------
// Creates a new handle
//-----------------------------------------------------------------------------
BSPTreeDataHandle_t CBSPTreeData::NewHandle( int userId )
{
BSPTreeDataHandle_t handle = m_Handles.AddToTail();
m_Handles[handle].m_UserId = userId;
m_Handles[handle].m_LeafList = m_HandleLeafList.InvalidIndex();
return handle;
}
//-----------------------------------------------------------------------------
// Add/remove handle
//-----------------------------------------------------------------------------
BSPTreeDataHandle_t CBSPTreeData::Insert( int userId, Vector const& mins, Vector const& maxs )
{
BSPTreeDataHandle_t handle = NewHandle( userId );
InsertIntoTree( handle, mins, maxs );
return handle;
}
void CBSPTreeData::Remove( BSPTreeDataHandle_t handle )
{
if (!m_Handles.IsValidIndex(handle))
return;
RemoveFromTree( handle );
m_Handles.Free( handle );
}
//-----------------------------------------------------------------------------
// Adds a handle to a leaf
//-----------------------------------------------------------------------------
void CBSPTreeData::AddHandleToLeaf( int leaf, BSPTreeDataHandle_t handle )
{
// Got to a leaf baby! Add the handle to the leaf's list of elements
unsigned short leafElement = m_LeafElements.Alloc( true );
if (m_Leaf[leaf].m_FirstElement != m_LeafElements.InvalidIndex() )
m_LeafElements.LinkBefore( m_Leaf[leaf].m_FirstElement, leafElement );
m_Leaf[leaf].m_FirstElement = leafElement;
m_LeafElements[leafElement] = handle;
// Insert the leaf into the handles's list of leaves
unsigned short handleElement = m_HandleLeafList.Alloc( true );
if (m_Handles[handle].m_LeafList != m_HandleLeafList.InvalidIndex() )
m_HandleLeafList.LinkBefore( m_Handles[handle].m_LeafList, handleElement );
m_Handles[handle].m_LeafList = handleElement;
m_HandleLeafList[handleElement].m_Leaf = leaf;
m_HandleLeafList[handleElement].m_LeafElementIndex = leafElement;
}
//-----------------------------------------------------------------------------
// Inserts an element into the tree
//-----------------------------------------------------------------------------
bool CBSPTreeData::EnumerateLeaf( int leaf, int context )
{
BSPTreeDataHandle_t handle = (BSPTreeDataHandle_t)context;
AddHandleToLeaf( leaf, handle );
return true;
}
void CBSPTreeData::InsertIntoTree( BSPTreeDataHandle_t handle, Vector const& mins, Vector const& maxs )
{
m_pBSPTree->EnumerateLeavesInBox( mins, maxs, this, handle );
}
//-----------------------------------------------------------------------------
// Removes an element from the tree
//-----------------------------------------------------------------------------
void CBSPTreeData::RemoveFromTree( BSPTreeDataHandle_t handle )
{
// Iterate over the list of all leaves the handle is in
unsigned short i = m_Handles[handle].m_LeafList;
while (i != m_HandleLeafList.InvalidIndex())
{
int leaf = m_HandleLeafList[i].m_Leaf;
unsigned short leafElement = m_HandleLeafList[i].m_LeafElementIndex;
// Unhook the handle from the leaf handle list
if (leafElement == m_Leaf[leaf].m_FirstElement)
m_Leaf[leaf].m_FirstElement = m_LeafElements.Next(leafElement);
m_LeafElements.Free(leafElement);
unsigned short prevNode = i;
i = m_HandleLeafList.Next(i);
m_HandleLeafList.Free(prevNode);
}
m_Handles[handle].m_LeafList = m_HandleLeafList.InvalidIndex();
}
//-----------------------------------------------------------------------------
// Call this when the element moves
//-----------------------------------------------------------------------------
void CBSPTreeData::ElementMoved( BSPTreeDataHandle_t handle, Vector const& mins, Vector const& maxs )
{
if (handle != TREEDATA_INVALID_HANDLE)
{
RemoveFromTree( handle );
InsertIntoTree( handle, mins, maxs );
}
}
//-----------------------------------------------------------------------------
// Is the element in any leaves at all?
//-----------------------------------------------------------------------------
bool CBSPTreeData::IsElementInTree( BSPTreeDataHandle_t handle ) const
{
return m_Handles[handle].m_LeafList != m_HandleLeafList.InvalidIndex();
}
//-----------------------------------------------------------------------------
// Enumerate elements in a particular leaf
//-----------------------------------------------------------------------------
int CBSPTreeData::CountElementsInLeaf( int leaf )
{
int i;
int nCount = 0;
for( i = m_Leaf[leaf].m_FirstElement; i != m_LeafElements.InvalidIndex(); i = m_LeafElements.Next(i) )
{
++nCount;
}
return nCount;
}
//-----------------------------------------------------------------------------
// Enumerate elements in a particular leaf
//-----------------------------------------------------------------------------
bool CBSPTreeData::EnumerateElementsInLeaf( int leaf, IBSPTreeDataEnumerator* pEnum, int context )
{
#ifdef DBGFLAG_ASSERT
// The enumeration method better damn well not change this list...
int nCount = CountElementsInLeaf(leaf);
#endif
unsigned short idx = m_Leaf[leaf].m_FirstElement;
while (idx != m_LeafElements.InvalidIndex())
{
BSPTreeDataHandle_t handle = m_LeafElements[idx];
if (!pEnum->EnumerateElement( m_Handles[handle].m_UserId, context ))
{
Assert( CountElementsInLeaf(leaf) == nCount );
return false;
}
idx = m_LeafElements.Next(idx);
}
Assert( CountElementsInLeaf(leaf) == nCount );
return true;
}
//-----------------------------------------------------------------------------
// For convenience, enumerates the leaves along a ray, box, etc.
//-----------------------------------------------------------------------------
bool CBSPTreeData::EnumerateLeavesAtPoint( Vector const& pt, ISpatialLeafEnumerator* pEnum, int context )
{
return m_pBSPTree->EnumerateLeavesAtPoint( pt, pEnum, context );
}
bool CBSPTreeData::EnumerateLeavesInBox( Vector const& mins, Vector const& maxs, ISpatialLeafEnumerator* pEnum, int context )
{
return m_pBSPTree->EnumerateLeavesInBox( mins, maxs, pEnum, context );
}
bool CBSPTreeData::EnumerateLeavesInSphere( Vector const& center, float radius, ISpatialLeafEnumerator* pEnum, int context )
{
return m_pBSPTree->EnumerateLeavesInSphere( center, radius, pEnum, context );
}
bool CBSPTreeData::EnumerateLeavesAlongRay( Ray_t const& ray, ISpatialLeafEnumerator* pEnum, int context )
{
return m_pBSPTree->EnumerateLeavesAlongRay( ray, pEnum, context );
}

136
public/bsptreedata.h Normal file
View File

@ -0,0 +1,136 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Revision: $
// $NoKeywords: $
//
// The BSP tree leaf data system
//
//=============================================================================//
#include "tier0/platform.h"
#if !defined( BSPTREEDATA )
#define BSPTREEDATA
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class Vector;
struct Ray_t;
//-----------------------------------------------------------------------------
// Handle to an renderable in the client leaf system
//-----------------------------------------------------------------------------
typedef unsigned short BSPTreeDataHandle_t;
enum
{
TREEDATA_INVALID_HANDLE = (BSPTreeDataHandle_t)~0
};
//-----------------------------------------------------------------------------
// Interface needed by tree data to do its job
//
// Note that anything that has convex spatial regions with leaves identified
// by indices can implement the ISpatialQuery. All you have to do is to implement
// a class that can answer the 5 questions in the Query interface about the
// spatial subdivision. For example, a K-D tree or a BSP tree could implement
// this interface
//
//-----------------------------------------------------------------------------
abstract_class ISpatialLeafEnumerator
{
public:
// call back with a leaf and a context
// The context is completely user defined; it's passed into the enumeration
// function of ISpatialQuery.
// This gets called by the enumeration methods with each leaf
// that passes the test; return true to continue enumerating,
// false to stop
virtual bool EnumerateLeaf( int leaf, int context ) = 0;
};
abstract_class ISpatialQuery
{
public:
// Returns the number of leaves
virtual int LeafCount() const = 0;
// Enumerates the leaves along a ray, box, etc.
virtual bool EnumerateLeavesAtPoint( Vector const& pt, ISpatialLeafEnumerator* pEnum, int context ) = 0;
virtual bool EnumerateLeavesInBox( Vector const& mins, Vector const& maxs, ISpatialLeafEnumerator* pEnum, int context ) = 0;
virtual bool EnumerateLeavesInSphere( Vector const& center, float radius, ISpatialLeafEnumerator* pEnum, int context ) = 0;
virtual bool EnumerateLeavesAlongRay( Ray_t const& ray, ISpatialLeafEnumerator* pEnum, int context ) = 0;
};
//-----------------------------------------------------------------------------
// Data associated with leaves.
//
// This is a parasitic class that attaches data to the leaves specified by the
// ISpatialQuery sent in to the initialization function. It can't exist without
// a spatial partition of some sort to hold onto.
//-----------------------------------------------------------------------------
abstract_class IBSPTreeDataEnumerator
{
public:
// call back with a userId and a context
virtual bool FASTCALL EnumerateElement( int userId, int context ) = 0;
};
abstract_class IBSPTreeData
{
public:
// Add a virtual destructor so that the derived class destructors will
// be called.
virtual ~IBSPTreeData() {}
// Initializes, shuts down
virtual void Init( ISpatialQuery* pBSPTree ) = 0;
virtual void Shutdown() = 0;
// Adds and removes data from the leaf lists
virtual BSPTreeDataHandle_t Insert( int userId, Vector const& mins, Vector const& maxs ) = 0;
virtual void Remove( BSPTreeDataHandle_t handle ) = 0;
// Call this when a element moves
virtual void ElementMoved( BSPTreeDataHandle_t handle, Vector const& mins, Vector const& maxs ) = 0;
// Enumerate elements in a particular leaf
virtual bool EnumerateElementsInLeaf( int leaf, IBSPTreeDataEnumerator* pEnum, int context ) = 0;
// Is the element in any leaves at all?
virtual bool IsElementInTree( BSPTreeDataHandle_t handle ) const = 0;
// NOTE: These methods call through to the functions in the attached
// ISpatialQuery
// For convenience, enumerates the leaves along a ray, box, etc.
virtual bool EnumerateLeavesAtPoint( Vector const& pt, ISpatialLeafEnumerator* pEnum, int context ) = 0;
virtual bool EnumerateLeavesInBox( Vector const& mins, Vector const& maxs, ISpatialLeafEnumerator* pEnum, int context ) = 0;
virtual bool EnumerateLeavesInSphere( Vector const& center, float radius, ISpatialLeafEnumerator* pEnum, int context ) = 0;
virtual bool EnumerateLeavesAlongRay( Ray_t const& ray, ISpatialLeafEnumerator* pEnum, int context ) = 0;
};
//-----------------------------------------------------------------------------
// Class factory
//-----------------------------------------------------------------------------
IBSPTreeData* CreateBSPTreeData();
void DestroyBSPTreeData( IBSPTreeData* pTreeData );
#endif // BSPTREEDATA

3116
public/builddisp.cpp Normal file

File diff suppressed because it is too large Load Diff

1460
public/builddisp.h Normal file

File diff suppressed because it is too large Load Diff

77
public/captioncompiler.h Normal file
View File

@ -0,0 +1,77 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef CAPTIONCOMPILER_H
#define CAPTIONCOMPILER_H
#ifdef _WIN32
#pragma once
#endif
#include "datamap.h"
#include "checksum_crc.h"
#define MAX_BLOCK_BITS 13
#define MAX_BLOCK_SIZE (1<<MAX_BLOCK_BITS )
#define COMPILED_CAPTION_FILEID MAKEID( 'V', 'C', 'C', 'D' )
#define COMPILED_CAPTION_VERSION 1
#pragma pack(1)
struct CompiledCaptionHeader_t
{
DECLARE_BYTESWAP_DATADESC()
int magic;
int version;
int numblocks;
int blocksize;
int directorysize;
int dataoffset;
};
struct CaptionLookup_t
{
DECLARE_BYTESWAP_DATADESC()
unsigned int hash;
int blockNum;
unsigned short offset;
unsigned short length;
void SetHash( char const *string )
{
int len = Q_strlen( string );
char *tempstr = (char *)_alloca( len + 1 );
Q_strncpy( tempstr, string, len + 1 );
Q_strlower( tempstr );
CRC32_t temp;
CRC32_Init( &temp );
CRC32_ProcessBuffer( &temp, tempstr, len );
CRC32_Final( &temp );
hash = ( unsigned int )temp;
}
};
#pragma pack()
class CCaptionLookupLess
{
public:
bool Less( const CaptionLookup_t& lhs, const CaptionLookup_t& rhs, void *pContext )
{
return lhs.hash < rhs.hash;
}
};
struct CaptionBlock_t
{
byte data[ MAX_BLOCK_SIZE ];
};
// For swapping compiled caption files
bool SwapClosecaptionFile( void *pData );
int UpdateOrCreateCaptionFile( const char *pSourceName, char *pTargetName, int targetLen, bool bForce = false );
#endif // CAPTIONCOMPILER_H

800
public/cdll_int.h Normal file
View File

@ -0,0 +1,800 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Interfaces between the client.dll and engine
//
//===========================================================================//
#ifndef CDLL_INT_H
#define CDLL_INT_H
#ifdef _WIN32
#pragma once
#endif
#include "basetypes.h"
#include "interface.h"
#include "mathlib/mathlib.h"
#include "const.h"
#include "checksum_crc.h"
#include "datamap.h"
#include "tier1/bitbuf.h"
#include "inputsystem/ButtonCode.h"
#include "modes.h"
#if !defined( _X360 )
#include "xbox/xboxstubs.h"
#endif
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
class ClientClass;
struct model_t;
class CSentence;
struct vrect_t;
struct cmodel_t;
class IMaterial;
class CAudioSource;
class CMeasureSection;
class SurfInfo;
class ISpatialQuery;
struct cache_user_t;
class IMaterialSystem;
class VMatrix;
struct ScreenFade_t;
struct ScreenShake_t;
class CViewSetup;
class CEngineSprite;
class CGlobalVarsBase;
class CPhysCollide;
class CSaveRestoreData;
class INetChannelInfo;
struct datamap_t;
struct typedescription_t;
class CStandardRecvProxies;
struct client_textmessage_t;
class IAchievementMgr;
class CGamestatsData;
class KeyValues;
class IFileList;
class CRenamedRecvTableInfo;
class CMouthInfo;
class IConVar;
//-----------------------------------------------------------------------------
// Purpose: This data structure is filled in by the engine when the client .dll requests information about
// other players that the engine knows about
//-----------------------------------------------------------------------------
// Engine player info, no game related infos here
// If you change this, change the two byteswap defintions:
// cdll_client_int.cpp and cdll_engine_int.cpp
typedef struct player_info_s
{
DECLARE_BYTESWAP_DATADESC();
// scoreboard information
char name[MAX_PLAYER_NAME_LENGTH];
// local server user ID, unique while server is running
int userID;
// global unique player identifer
char guid[SIGNED_GUID_LEN + 1];
// friends identification number
uint32 friendsID;
// friends name
char friendsName[MAX_PLAYER_NAME_LENGTH];
// true, if player is a bot controlled by game.dll
bool fakeplayer;
// true if player is the HLTV proxy
bool ishltv;
#if defined( REPLAY_ENABLED )
// true if player is the Replay proxy
bool isreplay;
#endif
// custom files CRC for this player
CRC32_t customFiles[MAX_CUSTOM_FILES];
// this counter increases each time the server downloaded a new file
unsigned char filesDownloaded;
} player_info_t;
//-----------------------------------------------------------------------------
// Hearing info
//-----------------------------------------------------------------------------
struct AudioState_t
{
Vector m_Origin;
QAngle m_Angles;
bool m_bIsUnderwater;
};
//-----------------------------------------------------------------------------
// Skybox visibility
//-----------------------------------------------------------------------------
enum SkyboxVisibility_t
{
SKYBOX_NOT_VISIBLE = 0,
SKYBOX_3DSKYBOX_VISIBLE,
SKYBOX_2DSKYBOX_VISIBLE,
};
//-----------------------------------------------------------------------------
// Skybox materials
//-----------------------------------------------------------------------------
struct SkyBoxMaterials_t
{
// order: "rt", "bk", "lf", "ft", "up", "dn"
IMaterial *material[6];
};
//-----------------------------------------------------------------------------
// Purpose: The engine reports to the client DLL what stage it's entering so the DLL can latch events
// and make sure that certain operations only happen during the right stages.
// The value for each stage goes up as you move through the frame so you can check ranges of values
// and if new stages get added in-between, the range is still valid.
//-----------------------------------------------------------------------------
enum ClientFrameStage_t
{
FRAME_UNDEFINED=-1, // (haven't run any frames yet)
FRAME_START,
// A network packet is being recieved
FRAME_NET_UPDATE_START,
// Data has been received and we're going to start calling PostDataUpdate
FRAME_NET_UPDATE_POSTDATAUPDATE_START,
// Data has been received and we've called PostDataUpdate on all data recipients
FRAME_NET_UPDATE_POSTDATAUPDATE_END,
// We've received all packets, we can now do interpolation, prediction, etc..
FRAME_NET_UPDATE_END,
// We're about to start rendering the scene
FRAME_RENDER_START,
// We've finished rendering the scene.
FRAME_RENDER_END
};
// Used by RenderView
enum RenderViewInfo_t
{
RENDERVIEW_UNSPECIFIED = 0,
RENDERVIEW_DRAWVIEWMODEL = (1<<0),
RENDERVIEW_DRAWHUD = (1<<1),
RENDERVIEW_SUPPRESSMONITORRENDERING = (1<<2),
};
//-----------------------------------------------------------------------------
// Lightcache entry handle
//-----------------------------------------------------------------------------
DECLARE_POINTER_HANDLE( LightCacheHandle_t );
//-----------------------------------------------------------------------------
// Occlusion parameters
//-----------------------------------------------------------------------------
struct OcclusionParams_t
{
float m_flMaxOccludeeArea;
float m_flMinOccluderArea;
};
//-----------------------------------------------------------------------------
// Just an interface version name for the random number interface
// See vstdlib/random.h for the interface definition
// NOTE: If you change this, also change VENGINE_SERVER_RANDOM_INTERFACE_VERSION in eiface.h
//-----------------------------------------------------------------------------
#define VENGINE_CLIENT_RANDOM_INTERFACE_VERSION "VEngineRandom001"
// change this when the new version is incompatable with the old
#define VENGINE_CLIENT_INTERFACE_VERSION "VEngineClient014"
#define VENGINE_CLIENT_INTERFACE_VERSION_13 "VEngineClient013"
//-----------------------------------------------------------------------------
// Purpose: Interface exposed from the engine to the client .dll
//-----------------------------------------------------------------------------
abstract_class IVEngineClient013
{
public:
// Find the model's surfaces that intersect the given sphere.
// Returns the number of surfaces filled in.
virtual int GetIntersectingSurfaces(
const model_t *model,
const Vector &vCenter,
const float radius,
const bool bOnlyVisibleSurfaces, // Only return surfaces visible to vCenter.
SurfInfo *pInfos,
const int nMaxInfos) = 0;
// Get the lighting intensivty for a specified point
// If bClamp is specified, the resulting Vector is restricted to the 0.0 to 1.0 for each element
virtual Vector GetLightForPoint(const Vector &pos, bool bClamp) = 0;
// Traces the line and reports the material impacted as well as the lighting information for the impact point
virtual IMaterial *TraceLineMaterialAndLighting( const Vector &start, const Vector &end,
Vector &diffuseLightColor, Vector& baseColor ) = 0;
// Given an input text buffer data pointer, parses a single token into the variable token and returns the new
// reading position
virtual const char *ParseFile( const char *data, char *token, int maxlen ) = 0;
virtual bool CopyLocalFile( const char *source, const char *destination ) = 0;
// Gets the dimensions of the game window
virtual void GetScreenSize( int& width, int& height ) = 0;
// Forwards szCmdString to the server, sent reliably if bReliable is set
virtual void ServerCmd( const char *szCmdString, bool bReliable = true ) = 0;
// Inserts szCmdString into the command buffer as if it was typed by the client to his/her console.
// Note: Calls to this are checked against FCVAR_CLIENTCMD_CAN_EXECUTE (if that bit is not set, then this function can't change it).
// Call ClientCmd_Unrestricted to have access to FCVAR_CLIENTCMD_CAN_EXECUTE vars.
virtual void ClientCmd( const char *szCmdString ) = 0;
// Fill in the player info structure for the specified player index (name, model, etc.)
virtual bool GetPlayerInfo( int ent_num, player_info_t *pinfo ) = 0;
// Retrieve the player entity number for a specified userID
virtual int GetPlayerForUserID( int userID ) = 0;
// Retrieves text message system information for the specified message by name
virtual client_textmessage_t *TextMessageGet( const char *pName ) = 0;
// Returns true if the console is visible
virtual bool Con_IsVisible( void ) = 0;
// Get the entity index of the local player
virtual int GetLocalPlayer( void ) = 0;
// Client DLL is hooking a model, loads the model into memory and returns pointer to the model_t
virtual const model_t *LoadModel( const char *pName, bool bProp = false ) = 0;
// Get accurate, sub-frame clock ( profiling use )
virtual float Time( void ) = 0;
// Get the exact server timesstamp ( server time ) from the last message received from the server
virtual float GetLastTimeStamp( void ) = 0;
// Given a CAudioSource (opaque pointer), retrieve the underlying CSentence object ( stores the words, phonemes, and close
// captioning data )
virtual CSentence *GetSentence( CAudioSource *pAudioSource ) = 0;
// Given a CAudioSource, determines the length of the underlying audio file (.wav, .mp3, etc.)
virtual float GetSentenceLength( CAudioSource *pAudioSource ) = 0;
// Returns true if the sound is streaming off of the hard disk (instead of being memory resident)
virtual bool IsStreaming( CAudioSource *pAudioSource ) const = 0;
// Copy current view orientation into va
virtual void GetViewAngles( QAngle& va ) = 0;
// Set current view orientation from va
virtual void SetViewAngles( QAngle& va ) = 0;
// Retrieve the current game's maxclients setting
virtual int GetMaxClients( void ) = 0;
// Given the string pBinding which may be bound to a key,
// returns the string name of the key to which this string is bound. Returns NULL if no such binding exists
virtual const char *Key_LookupBinding( const char *pBinding ) = 0;
// Given the name of the key "mouse1", "e", "tab", etc., return the string it is bound to "+jump", "impulse 50", etc.
virtual const char *Key_BindingForKey( ButtonCode_t code ) = 0;
// key trapping (for binding keys)
virtual void StartKeyTrapMode( void ) = 0;
virtual bool CheckDoneKeyTrapping( ButtonCode_t &code ) = 0;
// Returns true if the player is fully connected and active in game (i.e, not still loading)
virtual bool IsInGame( void ) = 0;
// Returns true if the player is connected, but not necessarily active in game (could still be loading)
virtual bool IsConnected( void ) = 0;
// Returns true if the loading plaque should be drawn
virtual bool IsDrawingLoadingImage( void ) = 0;
// Prints the formatted string to the notification area of the screen ( down the right hand edge
// numbered lines starting at position 0
virtual void Con_NPrintf( int pos, PRINTF_FORMAT_STRING const char *fmt, ... ) = 0;
// Similar to Con_NPrintf, but allows specifying custom text color and duration information
virtual void Con_NXPrintf( const struct con_nprint_s *info, PRINTF_FORMAT_STRING const char *fmt, ... ) = 0;
// Is the specified world-space bounding box inside the view frustum?
virtual int IsBoxVisible( const Vector& mins, const Vector& maxs ) = 0;
// Is the specified world-space boudning box in the same PVS cluster as the view origin?
virtual int IsBoxInViewCluster( const Vector& mins, const Vector& maxs ) = 0;
// Returns true if the specified box is outside of the view frustum and should be culled
virtual bool CullBox( const Vector& mins, const Vector& maxs ) = 0;
// Allow the sound system to paint additional data (during lengthy rendering operations) to prevent stuttering sound.
virtual void Sound_ExtraUpdate( void ) = 0;
// Get the current game directory ( e.g., hl2, tf2, cstrike, hl1 )
virtual const char *GetGameDirectory( void ) = 0;
// Get access to the world to screen transformation matrix
virtual const VMatrix& WorldToScreenMatrix() = 0;
// Get the matrix to move a point from world space into view space
// (translate and rotate so the camera is at the origin looking down X).
virtual const VMatrix& WorldToViewMatrix() = 0;
// The .bsp file can have mod-specified data lumps. These APIs are for working with such game lumps.
// Get mod-specified lump version id for the specified game data lump
virtual int GameLumpVersion( int lumpId ) const = 0;
// Get the raw size of the specified game data lump.
virtual int GameLumpSize( int lumpId ) const = 0;
// Loads a game lump off disk, writing the data into the buffer pointed to bye pBuffer
// Returns false if the data can't be read or the destination buffer is too small
virtual bool LoadGameLump( int lumpId, void* pBuffer, int size ) = 0;
// Returns the number of leaves in the level
virtual int LevelLeafCount() const = 0;
// Gets a way to perform spatial queries on the BSP tree
virtual ISpatialQuery* GetBSPTreeQuery() = 0;
// Convert texlight to gamma...
virtual void LinearToGamma( float* linear, float* gamma ) = 0;
// Get the lightstyle value
virtual float LightStyleValue( int style ) = 0;
// Computes light due to dynamic lighting at a point
// If the normal isn't specified, then it'll return the maximum lighting
virtual void ComputeDynamicLighting( const Vector& pt, const Vector* pNormal, Vector& color ) = 0;
// Returns the color of the ambient light
virtual void GetAmbientLightColor( Vector& color ) = 0;
// Returns the dx support level
virtual int GetDXSupportLevel() = 0;
// GR - returns the HDR support status
virtual bool SupportsHDR() = 0;
// Replace the engine's material system pointer.
virtual void Mat_Stub( IMaterialSystem *pMatSys ) = 0;
// Get the name of the current map
virtual void GetChapterName( char *pchBuff, int iMaxLength ) = 0;
virtual char const *GetLevelName( void ) = 0;
virtual int GetLevelVersion( void ) = 0;
#if !defined( NO_VOICE )
// Obtain access to the voice tweaking API
virtual struct IVoiceTweak_s *GetVoiceTweakAPI( void ) = 0;
#endif
// Tell engine stats gathering system that the rendering frame is beginning/ending
virtual void EngineStats_BeginFrame( void ) = 0;
virtual void EngineStats_EndFrame( void ) = 0;
// This tells the engine to fire any events (temp entity messages) that it has queued up this frame.
// It should only be called once per frame.
virtual void FireEvents() = 0;
// Returns an area index if all the leaves are in the same area. If they span multple areas, then it returns -1.
virtual int GetLeavesArea( int *pLeaves, int nLeaves ) = 0;
// Returns true if the box touches the specified area's frustum.
virtual bool DoesBoxTouchAreaFrustum( const Vector &mins, const Vector &maxs, int iArea ) = 0;
// Sets the hearing origin (i.e., the origin and orientation of the listener so that the sound system can spatialize
// sound appropriately ).
virtual void SetAudioState( const AudioState_t& state ) = 0;
// Sentences / sentence groups
virtual int SentenceGroupPick( int groupIndex, char *name, int nameBufLen ) = 0;
virtual int SentenceGroupPickSequential( int groupIndex, char *name, int nameBufLen, int sentenceIndex, int reset ) = 0;
virtual int SentenceIndexFromName( const char *pSentenceName ) = 0;
virtual const char *SentenceNameFromIndex( int sentenceIndex ) = 0;
virtual int SentenceGroupIndexFromName( const char *pGroupName ) = 0;
virtual const char *SentenceGroupNameFromIndex( int groupIndex ) = 0;
virtual float SentenceLength( int sentenceIndex ) = 0;
// Computes light due to dynamic lighting at a point
// If the normal isn't specified, then it'll return the maximum lighting
// If pBoxColors is specified (it's an array of 6), then it'll copy the light contribution at each box side.
virtual void ComputeLighting( const Vector& pt, const Vector* pNormal, bool bClamp, Vector& color, Vector *pBoxColors=NULL ) = 0;
// Activates/deactivates an occluder...
virtual void ActivateOccluder( int nOccluderIndex, bool bActive ) = 0;
virtual bool IsOccluded( const Vector &vecAbsMins, const Vector &vecAbsMaxs ) = 0;
// The save restore system allocates memory from a shared memory pool, use this allocator to allocate/free saverestore
// memory.
virtual void *SaveAllocMemory( size_t num, size_t size ) = 0;
virtual void SaveFreeMemory( void *pSaveMem ) = 0;
// returns info interface for client netchannel
virtual INetChannelInfo *GetNetChannelInfo( void ) = 0;
// Debugging functionality:
// Very slow routine to draw a physics model
virtual void DebugDrawPhysCollide( const CPhysCollide *pCollide, IMaterial *pMaterial, matrix3x4_t& transform, const color32 &color ) = 0;
// This can be used to notify test scripts that we're at a particular spot in the code.
virtual void CheckPoint( const char *pName ) = 0;
// Draw portals if r_DrawPortals is set (Debugging only)
virtual void DrawPortals() = 0;
// Determine whether the client is playing back or recording a demo
virtual bool IsPlayingDemo( void ) = 0;
virtual bool IsRecordingDemo( void ) = 0;
virtual bool IsPlayingTimeDemo( void ) = 0;
virtual int GetDemoRecordingTick( void ) = 0;
virtual int GetDemoPlaybackTick( void ) = 0;
virtual int GetDemoPlaybackStartTick( void ) = 0;
virtual float GetDemoPlaybackTimeScale( void ) = 0;
virtual int GetDemoPlaybackTotalTicks( void ) = 0;
// Is the game paused?
virtual bool IsPaused( void ) = 0;
// Is the game currently taking a screenshot?
virtual bool IsTakingScreenshot( void ) = 0;
// Is this a HLTV broadcast ?
virtual bool IsHLTV( void ) = 0;
// is this level loaded as just the background to the main menu? (active, but unplayable)
virtual bool IsLevelMainMenuBackground( void ) = 0;
// returns the name of the background level
virtual void GetMainMenuBackgroundName( char *dest, int destlen ) = 0;
// Get video modes
virtual void GetVideoModes( int &nCount, vmode_s *&pModes ) = 0;
// Occlusion system control
virtual void SetOcclusionParameters( const OcclusionParams_t &params ) = 0;
// What language is the user expecting to hear .wavs in, "english" or another...
virtual void GetUILanguage( char *dest, int destlen ) = 0;
// Can skybox be seen from a particular point?
virtual SkyboxVisibility_t IsSkyboxVisibleFromPoint( const Vector &vecPoint ) = 0;
// Get the pristine map entity lump string. (e.g., used by CS to reload the map entities when restarting a round.)
virtual const char* GetMapEntitiesString() = 0;
// Is the engine in map edit mode ?
virtual bool IsInEditMode( void ) = 0;
// current screen aspect ratio (eg. 4.0f/3.0f, 16.0f/9.0f)
virtual float GetScreenAspectRatio() = 0;
// allow the game UI to login a user
virtual bool REMOVED_SteamRefreshLogin( const char *password, bool isSecure ) = 0;
virtual bool REMOVED_SteamProcessCall( bool & finished ) = 0;
// allow other modules to know about engine versioning (one use is a proxy for network compatability)
virtual unsigned int GetEngineBuildNumber() = 0; // engines build
virtual const char * GetProductVersionString() = 0; // mods version number (steam.inf)
// Communicates to the color correction editor that it's time to grab the pre-color corrected frame
// Passes in the actual size of the viewport
virtual void GrabPreColorCorrectedFrame( int x, int y, int width, int height ) = 0;
virtual bool IsHammerRunning( ) const = 0;
// Inserts szCmdString into the command buffer as if it was typed by the client to his/her console.
// And then executes the command string immediately (vs ClientCmd() which executes in the next frame)
//
// Note: this is NOT checked against the FCVAR_CLIENTCMD_CAN_EXECUTE vars.
virtual void ExecuteClientCmd( const char *szCmdString ) = 0;
// returns if the loaded map was processed with HDR info. This will be set regardless
// of what HDR mode the player is in.
virtual bool MapHasHDRLighting(void) = 0;
virtual int GetAppID() = 0;
// Just get the leaf ambient light - no caching, no samples
virtual Vector GetLightForPointFast(const Vector &pos, bool bClamp) = 0;
// This version does NOT check against FCVAR_CLIENTCMD_CAN_EXECUTE.
virtual void ClientCmd_Unrestricted( const char *szCmdString ) = 0;
// This used to be accessible through the cl_restrict_server_commands cvar.
// By default, Valve games restrict the server to only being able to execute commands marked with FCVAR_SERVER_CAN_EXECUTE.
// By default, mods are allowed to execute any server commands, and they can restrict the server's ability to execute client
// commands with this function.
virtual void SetRestrictServerCommands( bool bRestrict ) = 0;
// If set to true (defaults to true for Valve games and false for others), then IVEngineClient::ClientCmd
// can only execute things marked with FCVAR_CLIENTCMD_CAN_EXECUTE.
virtual void SetRestrictClientCommands( bool bRestrict ) = 0;
// Sets the client renderable for an overlay's material proxy to bind to
virtual void SetOverlayBindProxy( int iOverlayID, void *pBindProxy ) = 0;
virtual bool CopyFrameBufferToMaterial( const char *pMaterialName ) = 0;
// Matchmaking
virtual void ChangeTeam( const char *pTeamName ) = 0;
// Causes the engine to read in the user's configuration on disk
virtual void ReadConfiguration( const bool readDefault = false ) = 0;
virtual void SetAchievementMgr( IAchievementMgr *pAchievementMgr ) = 0;
virtual IAchievementMgr *GetAchievementMgr() = 0;
virtual bool MapLoadFailed( void ) = 0;
virtual void SetMapLoadFailed( bool bState ) = 0;
virtual bool IsLowViolence() = 0;
virtual const char *GetMostRecentSaveGame( void ) = 0;
virtual void SetMostRecentSaveGame( const char *lpszFilename ) = 0;
virtual void StartXboxExitingProcess() = 0;
virtual bool IsSaveInProgress() = 0;
virtual uint OnStorageDeviceAttached( void ) = 0;
virtual void OnStorageDeviceDetached( void ) = 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
virtual void SetGamestatsData( CGamestatsData *pGamestatsData ) = 0;
virtual CGamestatsData *GetGamestatsData() = 0;
#if defined( USE_SDL ) || defined( OSX )
// we need to pull delta's from the cocoa mgr, the engine vectors this for us
virtual void GetMouseDelta( int &x, int &y, bool bIgnoreNextMouseDelta = false ) = 0;
#endif
// Sends a key values server command, not allowed from scripts execution
// Params:
// pKeyValues - key values to be serialized and sent to server
// the pointer is deleted inside the function: pKeyValues->deleteThis()
virtual void ServerCmdKeyValues( KeyValues *pKeyValues ) = 0;
virtual bool IsSkippingPlayback( void ) = 0;
virtual bool IsLoadingDemo( void ) = 0;
// Returns true if the engine is playing back a "locally recorded" demo, which includes
// both SourceTV and replay demos, since they're recorded locally (on servers), as opposed
// to a client recording a demo while connected to a remote server.
virtual bool IsPlayingDemoALocallyRecordedDemo() = 0;
// Given the string pBinding which may be bound to a key,
// returns the string name of the key to which this string is bound. Returns NULL if no such binding exists
// Unlike Key_LookupBinding, leading '+' characters are not stripped from bindings.
virtual const char *Key_LookupBindingExact( const char *pBinding ) = 0;
};
abstract_class IVEngineClient : public IVEngineClient013
{
public:
virtual uint GetProtocolVersion() = 0;
virtual bool IsWindowedMode() = 0;
// Flash the window (os specific)
virtual void FlashWindow() = 0;
// Client version from the steam.inf, this will be compared to the GC version
virtual int GetClientVersion() const = 0; // engines build
// Is App Active
virtual bool IsActiveApp() = 0;
virtual void DisconnectInternal() = 0;
};
//-----------------------------------------------------------------------------
// Purpose: Interface exposed from the client .dll back to the engine
//-----------------------------------------------------------------------------
abstract_class IBaseClientDLL
{
public:
// Called once when the client DLL is loaded
virtual int Init( CreateInterfaceFn appSystemFactory,
CreateInterfaceFn physicsFactory,
CGlobalVarsBase *pGlobals ) = 0;
virtual void PostInit() = 0;
// Called once when the client DLL is being unloaded
virtual void Shutdown( void ) = 0;
// Called once the client is initialized to setup client-side replay interface pointers
virtual bool ReplayInit( CreateInterfaceFn replayFactory ) = 0;
virtual bool ReplayPostInit() = 0;
// Called at the start of each level change
virtual void LevelInitPreEntity( char const* pMapName ) = 0;
// Called at the start of a new level, after the entities have been received and created
virtual void LevelInitPostEntity( ) = 0;
// Called at the end of a level
virtual void LevelShutdown( void ) = 0;
// Request a pointer to the list of client datatable classes
virtual ClientClass *GetAllClasses( void ) = 0;
// Called once per level to re-initialize any hud element drawing stuff
virtual int HudVidInit( void ) = 0;
// Called by the engine when gathering user input
virtual void HudProcessInput( bool bActive ) = 0;
// Called oncer per frame to allow the hud elements to think
virtual void HudUpdate( bool bActive ) = 0;
// Reset the hud elements to their initial states
virtual void HudReset( void ) = 0;
// Display a hud text message
virtual void HudText( const char * message ) = 0;
// Mouse Input Interfaces
// Activate the mouse (hides the cursor and locks it to the center of the screen)
virtual void IN_ActivateMouse( void ) = 0;
// Deactivates the mouse (shows the cursor and unlocks it)
virtual void IN_DeactivateMouse( void ) = 0;
// This is only called during extra sound updates and just accumulates mouse x, y offets and recenters the mouse.
// This call is used to try to prevent the mouse from appearing out of the side of a windowed version of the engine if
// rendering or other processing is taking too long
virtual void IN_Accumulate (void) = 0;
// Reset all key and mouse states to their initial, unpressed state
virtual void IN_ClearStates (void) = 0;
// If key is found by name, returns whether it's being held down in isdown, otherwise function returns false
virtual bool IN_IsKeyDown( const char *name, bool& isdown ) = 0;
// Notify the client that the mouse was wheeled while in game - called prior to executing any bound commands.
virtual void IN_OnMouseWheeled( int nDelta ) = 0;
// Raw keyboard signal, if the client .dll returns 1, the engine processes the key as usual, otherwise,
// if the client .dll returns 0, the key is swallowed.
virtual int IN_KeyEvent( int eventcode, ButtonCode_t keynum, const char *pszCurrentBinding ) = 0;
// This function is called once per tick to create the player CUserCmd (used for prediction/physics simulation of the player)
// Because the mouse can be sampled at greater than the tick interval, there is a separate input_sample_frametime, which
// specifies how much additional mouse / keyboard simulation to perform.
virtual void CreateMove (
int sequence_number, // sequence_number of this cmd
float input_sample_frametime, // Frametime for mouse input sampling
bool active ) = 0; // True if the player is active (not paused)
// If the game is running faster than the tick_interval framerate, then we do extra mouse sampling to avoid jittery input
// This code path is much like the normal move creation code, except no move is created
virtual void ExtraMouseSample( float frametime, bool active ) = 0;
// Encode the delta (changes) between the CUserCmd in slot from vs the one in slot to. The game code will have
// matching logic to read the delta.
virtual bool WriteUsercmdDeltaToBuffer( bf_write *buf, int from, int to, bool isnewcommand ) = 0;
// Demos need to be able to encode/decode CUserCmds to memory buffers, so these functions wrap that
virtual void EncodeUserCmdToBuffer( bf_write& buf, int slot ) = 0;
virtual void DecodeUserCmdFromBuffer( bf_read& buf, int slot ) = 0;
// Set up and render one or more views (e.g., rear view window, etc.). This called into RenderView below
virtual void View_Render( vrect_t *rect ) = 0;
// Allow engine to expressly render a view (e.g., during timerefresh)
// See IVRenderView.h, PushViewFlags_t for nFlags values
virtual void RenderView( const CViewSetup &view, int nClearFlags, int whatToDraw ) = 0;
// Apply screen fade directly from engine
virtual void View_Fade( ScreenFade_t *pSF ) = 0;
// The engine has parsed a crosshair angle message, this function is called to dispatch the new crosshair angle
virtual void SetCrosshairAngle( const QAngle& angle ) = 0;
// Sprite (.spr) model handling code
// Load a .spr file by name
virtual void InitSprite( CEngineSprite *pSprite, const char *loadname ) = 0;
// Shutdown a .spr file
virtual void ShutdownSprite( CEngineSprite *pSprite ) = 0;
// Returns sizeof( CEngineSprite ) so the engine can allocate appropriate memory
virtual int GetSpriteSize( void ) const = 0;
// Called when a player starts or stops talking.
// entindex is -1 to represent the local client talking (before the data comes back from the server).
// entindex is -2 to represent the local client's voice being acked by the server.
// entindex is GetPlayer() when the server acknowledges that the local client is talking.
virtual void VoiceStatus( int entindex, qboolean bTalking ) = 0;
// Networked string table definitions have arrived, allow client .dll to
// hook string changes with a callback function ( see INetworkStringTableClient.h )
virtual void InstallStringTableCallback( char const *tableName ) = 0;
// Notification that we're moving into another stage during the frame.
virtual void FrameStageNotify( ClientFrameStage_t curStage ) = 0;
// The engine has received the specified user message, this code is used to dispatch the message handler
virtual bool DispatchUserMessage( int msg_type, bf_read &msg_data ) = 0;
// Save/restore system hooks
virtual CSaveRestoreData *SaveInit( int size ) = 0;
virtual void SaveWriteFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ) = 0;
virtual void SaveReadFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ) = 0;
virtual void PreSave( CSaveRestoreData * ) = 0;
virtual void Save( CSaveRestoreData * ) = 0;
virtual void WriteSaveHeaders( CSaveRestoreData * ) = 0;
virtual void ReadRestoreHeaders( CSaveRestoreData * ) = 0;
virtual void Restore( CSaveRestoreData *, bool ) = 0;
virtual void DispatchOnRestore() = 0;
// Hand over the StandardRecvProxies in the client DLL's module.
virtual CStandardRecvProxies* GetStandardRecvProxies() = 0;
// save game screenshot writing
virtual void WriteSaveGameScreenshot( const char *pFilename ) = 0;
// Given a list of "S(wavname) S(wavname2)" tokens, look up the localized text and emit
// the appropriate close caption if running with closecaption = 1
virtual void EmitSentenceCloseCaption( char const *tokenstream ) = 0;
// Emits a regular close caption by token name
virtual void EmitCloseCaption( char const *captionname, float duration ) = 0;
// Returns true if the client can start recording a demo now. If the client returns false,
// an error message of up to length bytes should be returned in errorMsg.
virtual bool CanRecordDemo( char *errorMsg, int length ) const = 0;
// Give the Client a chance to do setup/cleanup.
virtual void OnDemoRecordStart( char const* pDemoBaseName ) = 0;
virtual void OnDemoRecordStop() = 0;
virtual void OnDemoPlaybackStart( char const* pDemoBaseName ) = 0;
virtual void OnDemoPlaybackStop() = 0;
// Draw the console overlay?
virtual bool ShouldDrawDropdownConsole() = 0;
// Get client screen dimensions
virtual int GetScreenWidth() = 0;
virtual int GetScreenHeight() = 0;
// Added interface
// save game screenshot writing
virtual void WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height, bool bCreatePowerOf2Padded = false, bool bWriteVTF = false ) = 0;
// Gets the current view
virtual bool GetPlayerView( CViewSetup &playerView ) = 0;
// Matchmaking
virtual void SetupGameProperties( CUtlVector< XUSER_CONTEXT > &contexts, CUtlVector< XUSER_PROPERTY > &properties ) = 0;
virtual uint GetPresenceID( const char *pIDName ) = 0;
virtual const char *GetPropertyIdString( const uint id ) = 0;
virtual void GetPropertyDisplayString( uint id, uint value, char *pOutput, int nBytes ) = 0;
#ifdef WIN32
virtual void StartStatsReporting( HANDLE handle, bool bArbitrated ) = 0;
#endif
virtual void InvalidateMdlCache() = 0;
virtual void IN_SetSampleTime( float frametime ) = 0;
// For sv_pure mode. The filesystem figures out which files the client needs to reload to be "pure" ala the server's preferences.
virtual void ReloadFilesInList( IFileList *pFilesToReload ) = 0;
#ifdef POSIX
// AR: Same as above win32 defn but down here at the end of the vtable for back compat
virtual void StartStatsReporting( HANDLE handle, bool bArbitrated ) = 0;
#endif
// Let the client handle UI toggle - if this function returns false, the UI will toggle, otherwise it will not.
virtual bool HandleUiToggle() = 0;
// Allow the console to be shown?
virtual bool ShouldAllowConsole() = 0;
// Get renamed recv tables
virtual CRenamedRecvTableInfo *GetRenamedRecvTableInfos() = 0;
// Get the mouthinfo for the sound being played inside UI panels
virtual CMouthInfo *GetClientUIMouthInfo() = 0;
// Notify the client that a file has been received from the game server
virtual void FileReceived( const char * fileName, unsigned int transferID ) = 0;
virtual const char* TranslateEffectForVisionFilter( const char *pchEffectType, const char *pchEffectName ) = 0;
// Give the client a chance to modify sound settings however they want before the sound plays. This is used for
// things like adjusting pitch of voice lines in Pyroland in TF2.
virtual void ClientAdjustStartSoundParams( struct StartSoundParams_t& params ) = 0;
// Returns true if the disconnect command has been handled by the client
virtual bool DisconnectAttempt( void ) = 0;
virtual bool IsConnectedUserInfoChangeAllowed( IConVar *pCvar ) = 0;
};
#define CLIENT_DLL_INTERFACE_VERSION "VClient017"
//-----------------------------------------------------------------------------
// Purpose: Interface exposed from the client .dll back to the engine for specifying shared .dll IAppSystems (e.g., ISoundEmitterSystem)
//-----------------------------------------------------------------------------
abstract_class IClientDLLSharedAppSystems
{
public:
virtual int Count() = 0;
virtual char const *GetDllName( int idx ) = 0;
virtual char const *GetInterfaceName( int idx ) = 0;
};
#define CLIENT_DLL_SHARED_APPSYSTEMS "VClientDllSharedAppSystems001"
#endif // CDLL_INT_H

985
public/chunkfile.cpp Normal file
View File

@ -0,0 +1,985 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implements an interface for reading and writing heirarchical
// text files of key value pairs. The format of the file is as follows:
//
// chunkname0
// {
// "key0" "value0"
// "key1" "value1"
// ...
// "keyN" "valueN"
// chunkname1
// {
// "key0" "value0"
// "key1" "value1"
// ...
// "keyN" "valueN"
// }
// }
// ...
// chunknameN
// {
// "key0" "value0"
// "key1" "value1"
// ...
// "keyN" "valueN"
// }
//
// The chunk names are not necessarily unique, nor are the key names, unless the
// parsing application requires them to be.
//
// $NoKeywords: $
//=============================================================================//
#include <fcntl.h>
#ifdef _WIN32
#include <io.h>
#endif
#include <math.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "chunkfile.h"
#include "mathlib/vector.h"
#include "mathlib/vector4d.h"
#include "tier1/strtools.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: Constructor.
//-----------------------------------------------------------------------------
CChunkHandlerMap::CChunkHandlerMap(void)
{
m_pHandlers = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor. Frees handler list.
//-----------------------------------------------------------------------------
CChunkHandlerMap::~CChunkHandlerMap(void)
{
ChunkHandlerInfoNode_t *pNode = m_pHandlers;
while (pNode != NULL)
{
ChunkHandlerInfoNode_t *pPrev = pNode;
pNode = pNode->pNext;
delete pPrev;
}
}
//-----------------------------------------------------------------------------
// Purpose: Adds a chunk handler to the handler list.
// Input : pszChunkName - Name of chunk to be handled.
// pfnHandler - Address of handler callback function.
// pData - Data to pass to the handler callback.
//-----------------------------------------------------------------------------
void CChunkHandlerMap::AddHandler(const char *pszChunkName, ChunkHandler_t pfnHandler, void *pData)
{
ChunkHandlerInfoNode_t *pNew = new ChunkHandlerInfoNode_t;
Q_strncpy(pNew->Handler.szChunkName, pszChunkName, sizeof( pNew->Handler.szChunkName ));
pNew->Handler.pfnHandler = pfnHandler;
pNew->Handler.pData = pData;
pNew->pNext = NULL;
if (m_pHandlers == NULL)
{
m_pHandlers = pNew;
}
else
{
ChunkHandlerInfoNode_t *pNode = m_pHandlers;
while (pNode->pNext != NULL)
{
pNode = pNode->pNext;
}
pNode->pNext = pNew;
}
}
//-----------------------------------------------------------------------------
// Purpose: Sets the callback for error handling within this chunk's scope.
// Input : pfnHandler -
// pData -
//-----------------------------------------------------------------------------
void CChunkHandlerMap::SetErrorHandler(ChunkErrorHandler_t pfnHandler, void *pData)
{
m_pfnErrorHandler = pfnHandler;
m_pErrorData = pData;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : ppData -
// Output : ChunkErrorHandler_t
//-----------------------------------------------------------------------------
ChunkErrorHandler_t CChunkHandlerMap::GetErrorHandler(void **ppData)
{
*ppData = m_pErrorData;
return(m_pfnErrorHandler);
}
//-----------------------------------------------------------------------------
// Purpose: Gets the handler for a given chunk name, if one has been set.
// Input : pszChunkName - Name of chunk.
// ppfnHandler - Receives the address of the callback function.
// ppData - Receives the context data for the given chunk.
// Output : Returns true if a handler was found, false if not.
//-----------------------------------------------------------------------------
ChunkHandler_t CChunkHandlerMap::GetHandler(const char *pszChunkName, void **ppData)
{
ChunkHandlerInfoNode_t *pNode = m_pHandlers;
while (pNode != NULL)
{
if (!stricmp(pNode->Handler.szChunkName, pszChunkName))
{
*ppData = pNode->Handler.pData;
return(pNode->Handler.pfnHandler);
}
pNode = pNode->pNext;
}
return(false);
}
//-----------------------------------------------------------------------------
// Purpose: Constructor. Initializes data members.
//-----------------------------------------------------------------------------
CChunkFile::CChunkFile(void)
{
m_hFile = NULL;
m_nCurrentDepth = 0;
m_szIndent[0] = '\0';
m_nHandlerStackDepth = 0;
m_DefaultChunkHandler = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor. Closes the file if it is currently open.
//-----------------------------------------------------------------------------
CChunkFile::~CChunkFile(void)
{
if (m_hFile != NULL)
{
fclose(m_hFile);
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pszChunkName -
// Output : ChunkFileResult_t
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::BeginChunk(const char *pszChunkName)
{
//
// Write the chunk name and open curly.
//
char szBuf[MAX_KEYVALUE_LEN];
Q_snprintf(szBuf, sizeof( szBuf ), "%s\r\n%s{", pszChunkName, m_szIndent);
ChunkFileResult_t eResult = WriteLine(szBuf);
//
// Update the indentation depth.
//
if (eResult == ChunkFile_Ok)
{
m_nCurrentDepth++;
BuildIndentString(m_szIndent, m_nCurrentDepth);
}
return(eResult);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CChunkFile::BuildIndentString(char *pszDest, int nDepth)
{
if (nDepth >= 0)
{
for (int i = 0; i < nDepth; i++)
{
pszDest[i] = '\t';
}
pszDest[nDepth] = '\0';
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : ChunkFileResult_t
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::Close(void)
{
if (m_hFile != NULL)
{
fclose(m_hFile);
m_hFile = NULL;
}
return(ChunkFile_Ok);
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : ChunkFileResult_t
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::EndChunk(void)
{
if (m_nCurrentDepth > 0)
{
m_nCurrentDepth--;
BuildIndentString(m_szIndent, m_nCurrentDepth);
}
WriteLine("}");
return(ChunkFile_Ok);
}
//-----------------------------------------------------------------------------
// Purpose: Returns a string explaining the last error that occurred.
//-----------------------------------------------------------------------------
const char *CChunkFile::GetErrorText(ChunkFileResult_t eResult)
{
static char szError[MAX_KEYVALUE_LEN];
switch (eResult)
{
case ChunkFile_UnexpectedEOF:
{
Q_strncpy(szError, "unexpected end of file", sizeof( szError ) );
break;
}
case ChunkFile_UnexpectedSymbol:
{
Q_snprintf(szError, sizeof( szError ), "unexpected symbol '%s'", m_szErrorToken);
break;
}
case ChunkFile_OpenFail:
{
Q_snprintf(szError, sizeof( szError ), "%s", strerror(errno)) ;
break;
}
case ChunkFile_StringTooLong:
{
Q_strncpy(szError, "unterminated string or string too long", sizeof( szError ) );
break;
}
default:
{
Q_snprintf(szError, sizeof( szError ), "error %d", eResult);
}
}
return(m_TokenReader.Error(szError));
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : eError -
//-----------------------------------------------------------------------------
void CChunkFile::HandleError(const char *szChunkName, ChunkFileResult_t eError)
{
// UNDONE: dispatch errors to the error handler.
// - keep track of current chunkname for reporting errors
// - use the last non-NULL handler that was pushed onto the stack?
// - need a return code to determine whether to abort parsing?
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : ChunkFileResult_t
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::HandleChunk(const char *szChunkName)
{
// See if the default handler wants it?
if( m_DefaultChunkHandler )
{
ChunkFileResult_t testResult = m_DefaultChunkHandler( this, m_pDefaultChunkHandlerData, szChunkName );
if( testResult == ChunkFile_Ok )
{
return ChunkFile_Ok;
}
}
//
// If there is an active handler map...
//
if (m_nHandlerStackDepth > 0)
{
CChunkHandlerMap *pHandler = m_HandlerStack[m_nHandlerStackDepth - 1];
//
// If a chunk handler was found in the handler map...
//
void *pData;
ChunkHandler_t pfnHandler = pHandler->GetHandler(szChunkName, &pData);
if (pfnHandler != NULL)
{
// Dispatch this chunk to the handler.
ChunkFileResult_t eResult = pfnHandler(this, pData);
if (eResult != ChunkFile_Ok)
{
return(eResult);
}
}
else
{
//
// No handler for this chunk. Skip to the matching close curly brace.
//
int nDepth = 1;
ChunkFileResult_t eResult;
do
{
ChunkType_t eChunkType;
char szKey[MAX_KEYVALUE_LEN];
char szValue[MAX_KEYVALUE_LEN];
while ((eResult = ReadNext(szKey, szValue, sizeof(szValue), eChunkType)) == ChunkFile_Ok)
{
if (eChunkType == ChunkType_Chunk)
{
nDepth++;
}
}
if (eResult == ChunkFile_EndOfChunk)
{
eResult = ChunkFile_Ok;
nDepth--;
}
else if (eResult == ChunkFile_EOF)
{
return(ChunkFile_UnexpectedEOF);
}
} while ((nDepth) && (eResult == ChunkFile_Ok));
}
}
return(ChunkFile_Ok);
}
//-----------------------------------------------------------------------------
// Purpose: Opens the chunk file for reading or writing.
// Input : pszFileName - Path of file to open.
// eMode - ChunkFile_Read or ChunkFile_Write.
// Output : Returns ChunkFile_Ok on success, ChunkFile_Fail on failure.
// UNDONE: boolean return value?
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::Open(const char *pszFileName, ChunkFileOpenMode_t eMode)
{
if (eMode == ChunkFile_Read)
{
// UNDONE: TokenReader encapsulates file - unify reading and writing to use the same file I/O.
// UNDONE: Support in-memory parsing.
if (m_TokenReader.Open(pszFileName))
{
m_nCurrentDepth = 0;
}
else
{
return(ChunkFile_OpenFail);
}
}
else if (eMode == ChunkFile_Write)
{
m_hFile = fopen(pszFileName, "wb");
if (m_hFile == NULL)
{
return(ChunkFile_OpenFail);
}
m_nCurrentDepth = 0;
}
return(ChunkFile_Ok);
}
//-----------------------------------------------------------------------------
// Purpose: Removes the topmost set of chunk handlers.
//-----------------------------------------------------------------------------
void CChunkFile::PopHandlers(void)
{
if (m_nHandlerStackDepth > 0)
{
m_nHandlerStackDepth--;
}
}
void CChunkFile::SetDefaultChunkHandler( DefaultChunkHandler_t pHandler, void *pData )
{
m_DefaultChunkHandler = pHandler;
m_pDefaultChunkHandlerData = pData;}
//-----------------------------------------------------------------------------
// Purpose: Adds a set of chunk handlers to the top of the handler stack.
// Input : pHandlerMap - Object containing the list of chunk handlers.
//-----------------------------------------------------------------------------
void CChunkFile::PushHandlers(CChunkHandlerMap *pHandlerMap)
{
if (m_nHandlerStackDepth < MAX_INDENT_DEPTH)
{
m_HandlerStack[m_nHandlerStackDepth] = pHandlerMap;
m_nHandlerStackDepth++;
}
}
//-----------------------------------------------------------------------------
// Purpose: Reads the next term from the chunk file. The type of term read is
// returned in the eChunkType parameter.
// Input : szName - Name of key or chunk.
// szValue - If eChunkType is ChunkType_Key, contains the value of the key.
// nValueSize - Size of the buffer pointed to by szValue.
// eChunkType - ChunkType_Key or ChunkType_Chunk.
// Output : Returns ChunkFile_Ok on success, an error code if a parsing error occurs.
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::ReadNext(char *szName, char *szValue, int nValueSize, ChunkType_t &eChunkType)
{
// HACK: pass in buffer sizes?
trtoken_t eTokenType = m_TokenReader.NextToken(szName, MAX_KEYVALUE_LEN);
if (eTokenType != TOKENEOF)
{
switch (eTokenType)
{
case IDENT:
case STRING:
{
char szNext[MAX_KEYVALUE_LEN];
trtoken_t eNextTokenType;
//
// Read the next token to determine what we have.
//
eNextTokenType = m_TokenReader.NextToken(szNext, sizeof(szNext));
switch (eNextTokenType)
{
case OPERATOR:
{
if (!stricmp(szNext, "{"))
{
// Beginning of new chunk.
m_nCurrentDepth++;
eChunkType = ChunkType_Chunk;
szValue[0] = '\0';
return(ChunkFile_Ok);
}
else
{
// Unexpected symbol.
Q_strncpy(m_szErrorToken, szNext, sizeof( m_szErrorToken ) );
return(ChunkFile_UnexpectedSymbol);
}
}
case STRING:
case IDENT:
{
// Key value pair.
Q_strncpy(szValue, szNext, nValueSize );
eChunkType = ChunkType_Key;
return(ChunkFile_Ok);
}
case TOKENEOF:
{
// Unexpected end of file.
return(ChunkFile_UnexpectedEOF);
}
case TOKENSTRINGTOOLONG:
{
// String too long or unterminated string.
return ChunkFile_StringTooLong;
}
}
}
case OPERATOR:
{
if (!stricmp(szName, "}"))
{
// End of current chunk.
m_nCurrentDepth--;
return(ChunkFile_EndOfChunk);
}
else
{
// Unexpected symbol.
Q_strncpy(m_szErrorToken, szName, sizeof( m_szErrorToken ) );
return(ChunkFile_UnexpectedSymbol);
}
}
case TOKENSTRINGTOOLONG:
{
return ChunkFile_StringTooLong;
}
}
}
if (m_nCurrentDepth != 0)
{
// End of file while within the scope of a chunk.
return(ChunkFile_UnexpectedEOF);
}
return(ChunkFile_EOF);
}
//-----------------------------------------------------------------------------
// Purpose: Reads the current chunk and dispatches keys and sub-chunks to the
// appropriate handler callbacks.
// Input : pfnKeyHandler - Callback for any key values in this chunk.
// pData - Data to pass to the key value callback function.
// Output : Normally returns ChunkFile_Ok or ChunkFile_EOF. Otherwise, returns
// a ChunkFile_xxx error code.
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::ReadChunk(KeyHandler_t pfnKeyHandler, void *pData)
{
//
// Read the keys and sub-chunks.
//
ChunkFileResult_t eResult;
do
{
char szName[MAX_KEYVALUE_LEN];
char szValue[MAX_KEYVALUE_LEN];
ChunkType_t eChunkType;
eResult = ReadNext(szName, szValue, sizeof(szValue), eChunkType);
if (eResult == ChunkFile_Ok)
{
if (eChunkType == ChunkType_Chunk)
{
//
// Dispatch sub-chunks to the appropriate handler.
//
eResult = HandleChunk(szName);
}
else if ((eChunkType == ChunkType_Key) && (pfnKeyHandler != NULL))
{
//
// Dispatch keys to the key value handler.
//
eResult = pfnKeyHandler(szName, szValue, pData);
}
}
} while (eResult == ChunkFile_Ok);
//
// Cover up ChunkFile_EndOfChunk results because the caller doesn't want to see them.
//
if (eResult == ChunkFile_EndOfChunk)
{
eResult = ChunkFile_Ok;
}
//
// Dispatch errors to the handler.
//
if ((eResult != ChunkFile_Ok) && (eResult != ChunkFile_EOF))
{
//HandleError("chunkname", eResult);
}
return(eResult);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszValue -
// pbBool -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CChunkFile::ReadKeyValueBool(const char *pszValue, bool &bBool)
{
int nValue = atoi(pszValue);
if (nValue > 0)
{
bBool = true;
}
else
{
bBool = false;
}
return(true);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszValue -
// pfFloat -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CChunkFile::ReadKeyValueFloat(const char *pszValue, float &flFloat)
{
flFloat = (float)atof(pszValue);
return(true);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszValue -
// pnInt -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CChunkFile::ReadKeyValueInt(const char *pszValue, int &nInt)
{
nInt = atoi(pszValue);
return(true);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszKey -
// r -
// g -
// b -
// Output :
//-----------------------------------------------------------------------------
bool CChunkFile::ReadKeyValueColor(const char *pszValue, unsigned char &chRed, unsigned char &chGreen, unsigned char &chBlue)
{
if (pszValue != NULL)
{
int r = 0;
int g = 0;
int b = 0;
if (sscanf(pszValue, "%d %d %d", &r, &g, &b) == 3)
{
chRed = r;
chGreen = g;
chBlue = b;
return(true);
}
}
return(false);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszValue -
// pfPoint -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CChunkFile::ReadKeyValuePoint(const char *pszValue, Vector &Point)
{
if (pszValue != NULL)
{
return(sscanf(pszValue, "(%f %f %f)", &Point.x, &Point.y, &Point.z) == 3);
}
return(false);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszValue -
// pfVector -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CChunkFile::ReadKeyValueVector2(const char *pszValue, Vector2D &vec)
{
if (pszValue != NULL)
{
return ( sscanf( pszValue, "[%f %f]", &vec.x, &vec.y) == 2 );
}
return(false);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszValue -
// pfVector -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CChunkFile::ReadKeyValueVector3(const char *pszValue, Vector &vec)
{
if (pszValue != NULL)
{
return(sscanf(pszValue, "[%f %f %f]", &vec.x, &vec.y, &vec.z) == 3);
}
return(false);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszValue -
// pfVector -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CChunkFile::ReadKeyValueVector4(const char *pszValue, Vector4D &vec)
{
if( pszValue != NULL )
{
return(sscanf(pszValue, "[%f %f %f %f]", &vec[0], &vec[1], &vec[2], &vec[3]) == 4);
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszLine -
// Output :
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::WriteKeyValue(const char *pszKey, const char *pszValue)
{
if ((pszKey != NULL) && (pszValue != NULL))
{
char szTemp[MAX_KEYVALUE_LEN];
Q_snprintf(szTemp, sizeof( szTemp ), "\"%s\" \"%s\"", pszKey, pszValue);
return(WriteLine(szTemp));
}
return(ChunkFile_Ok);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszKey -
// bValue -
// Output :
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::WriteKeyValueBool(const char *pszKey, bool bValue)
{
if (pszKey != NULL)
{
char szBuf[MAX_KEYVALUE_LEN];
Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"%d\"", pszKey, (int)bValue);
return(WriteLine(szBuf));
}
return(ChunkFile_Ok);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszKey -
// nValue -
// Output :
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::WriteKeyValueInt(const char *pszKey, int nValue)
{
if (pszKey != NULL)
{
char szBuf[MAX_KEYVALUE_LEN];
Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"%d\"", pszKey, nValue);
return(WriteLine(szBuf));
}
return(ChunkFile_Ok);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszKey -
// fValue -
// Output :
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::WriteKeyValueFloat(const char *pszKey, float fValue)
{
if (pszKey != NULL)
{
char szBuf[MAX_KEYVALUE_LEN];
Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"%g\"", pszKey, (double)fValue);
return(WriteLine(szBuf));
}
return(ChunkFile_Ok);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszKey -
// r -
// g -
// b -
// Output :
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::WriteKeyValueColor(const char *pszKey, unsigned char r, unsigned char g, unsigned char b)
{
if (pszKey != NULL)
{
char szBuf[MAX_KEYVALUE_LEN];
Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"%d %d %d\"", pszKey, (int)r, (int)g, (int)b);
return(WriteLine(szBuf));
}
return(ChunkFile_Ok);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszKey -
// fVector -
// Output :
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::WriteKeyValuePoint(const char *pszKey, const Vector &Point)
{
if (pszKey != NULL)
{
char szBuf[MAX_KEYVALUE_LEN];
Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"(%g %g %g)\"", pszKey, (double)Point[0], (double)Point[1], (double)Point[2]);
return(WriteLine(szBuf));
}
return(ChunkFile_Ok);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::WriteKeyValueVector2(const char *pszKey, const Vector2D &vec)
{
if (pszKey != NULL)
{
char szBuf[MAX_KEYVALUE_LEN];
Q_snprintf( szBuf, sizeof( szBuf ), "\"%s\" \"[%g %g]\"", pszKey, (double)vec.x, (double)vec.y );
return(WriteLine(szBuf));
}
return(ChunkFile_Ok);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::WriteKeyValueVector3(const char *pszKey, const Vector &vec)
{
if (pszKey != NULL)
{
char szBuf[MAX_KEYVALUE_LEN];
Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"[%g %g %g]\"", pszKey, (double)vec.x, (double)vec.y, (double)vec.z);
return(WriteLine(szBuf));
}
return(ChunkFile_Ok);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszKey -
// fVector -
// Output :
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::WriteKeyValueVector4(const char *pszKey, const Vector4D &vec)
{
if (pszKey != NULL)
{
char szBuf[MAX_KEYVALUE_LEN];
Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"[%g %g %g %g]\"", pszKey, (double)vec.x, (double)vec.y, (double)vec.z, (double)vec.w);
return( WriteLine( szBuf ) );
}
return( ChunkFile_Ok );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pszLine -
// Output :
//-----------------------------------------------------------------------------
ChunkFileResult_t CChunkFile::WriteLine(const char *pszLine)
{
if (pszLine != NULL)
{
//
// Write the indentation string.
//
if (m_nCurrentDepth > 0)
{
int nWritten = fwrite(m_szIndent, 1, m_nCurrentDepth, m_hFile);
if (nWritten != m_nCurrentDepth)
{
return(ChunkFile_Fail);
}
}
//
// Write the string.
//
int nLen = strlen(pszLine);
int nWritten = fwrite(pszLine, 1, nLen, m_hFile);
if (nWritten != nLen)
{
return(ChunkFile_Fail);
}
//
// Write the linefeed.
//
if (fwrite("\r\n", 1, 2, m_hFile) != 2)
{
return(ChunkFile_Fail);
}
}
return(ChunkFile_Ok);
}

197
public/chunkfile.h Normal file
View File

@ -0,0 +1,197 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef CHUNKFILE_H
#define CHUNKFILE_H
#ifdef _WIN32
#pragma once
#endif
#include <stdio.h>
#include "tokenreader.h"
#define MAX_INDENT_DEPTH 80
#define MAX_KEYVALUE_LEN 1024
class CChunkFile;
class Vector2D;
class Vector;
class Vector4D;
//
// Modes for Open.
//
enum ChunkFileOpenMode_t
{
ChunkFile_Read = 0,
ChunkFile_Write,
};
//
// Return codes.
//
enum ChunkFileResult_t
{
ChunkFile_Ok = 0,
ChunkFile_Fail,
ChunkFile_OpenFail,
ChunkFile_EndOfChunk,
ChunkFile_EOF,
ChunkFile_UnexpectedEOF,
ChunkFile_UnexpectedSymbol,
ChunkFile_OutOfMemory,
ChunkFile_StringTooLong,
ChunkFile_NotHandled
};
enum ChunkType_t
{
ChunkType_Key = 0,
ChunkType_Chunk,
};
typedef ChunkFileResult_t (*DefaultChunkHandler_t)(CChunkFile *pFile, void *pData, char const *pChunkName);
typedef ChunkFileResult_t (*ChunkHandler_t)(CChunkFile *pFile, void *pData);
typedef ChunkFileResult_t (*KeyHandler_t)(const char *szKey, const char *szValue, void *pData);
typedef bool (*ChunkErrorHandler_t)(CChunkFile *pFile, const char *szChunkName, void *pData);
struct ChunkHandlerInfo_t
{
char szChunkName[80];
ChunkHandler_t pfnHandler;
void *pData;
};
struct ChunkHandlerInfoNode_t
{
ChunkHandlerInfo_t Handler;
struct ChunkHandlerInfoNode_t *pNext;
};
//
// Consider handling chunks with handler objects instead of callbacks.
//
//class CChunkHandler
//{
// virtual ChunkFileResult_t HandleChunk(const char *szName);
// virtual ChunkFileResult_t HandleKey(const char *szKey, const char *szValue);
// virtual bool HandleError(const char *szChunkName, ChunkFileResult_t eError);
//};
class CChunkHandlerMap
{
public:
CChunkHandlerMap(void);
~CChunkHandlerMap(void);
void AddHandler(const char *pszChunkName, ChunkHandler_t pfnHandler, void *pData);
ChunkHandler_t GetHandler(const char *pszChunkName, void **pData);
void SetErrorHandler(ChunkErrorHandler_t pfnHandler, void *pData);
ChunkErrorHandler_t GetErrorHandler(void **pData);
protected:
ChunkHandlerInfoNode_t *m_pHandlers;
ChunkErrorHandler_t m_pfnErrorHandler;
void *m_pErrorData;
};
class CChunkFile
{
public:
CChunkFile(void);
~CChunkFile(void);
ChunkFileResult_t Open(const char *pszFileName, ChunkFileOpenMode_t eMode);
ChunkFileResult_t Close(void);
const char *GetErrorText(ChunkFileResult_t eResult);
//
// Functions for writing chunk files.
//
ChunkFileResult_t BeginChunk(const char *pszChunkName);
ChunkFileResult_t EndChunk(void);
ChunkFileResult_t WriteKeyValue(const char *pszKey, const char *pszValue);
ChunkFileResult_t WriteKeyValueBool(const char *pszKey, bool bValue);
ChunkFileResult_t WriteKeyValueColor(const char *pszKey, unsigned char r, unsigned char g, unsigned char b);
ChunkFileResult_t WriteKeyValueFloat(const char *pszKey, float fValue);
ChunkFileResult_t WriteKeyValueInt(const char *pszKey, int nValue);
ChunkFileResult_t WriteKeyValuePoint(const char *pszKey, const Vector &Point);
ChunkFileResult_t WriteKeyValueVector2(const char *pszKey, const Vector2D &vec);
ChunkFileResult_t WriteKeyValueVector3(const char *pszKey, const Vector &vec);
ChunkFileResult_t WriteKeyValueVector4( const char *pszKey, const Vector4D &vec);
ChunkFileResult_t WriteLine(const char *pszLine);
//
// Functions for reading chunk files.
//
ChunkFileResult_t ReadChunk(KeyHandler_t pfnKeyHandler = NULL, void *pData = NULL);
ChunkFileResult_t ReadNext(char *szKey, char *szValue, int nValueSize, ChunkType_t &eChunkType);
ChunkFileResult_t HandleChunk(const char *szChunkName);
void HandleError(const char *szChunkName, ChunkFileResult_t eError);
// These functions should more really be named Parsexxx and possibly moved elsewhere.
static bool ReadKeyValueBool(const char *pszValue, bool &bBool);
static bool ReadKeyValueColor(const char *pszValue, unsigned char &chRed, unsigned char &chGreen, unsigned char &chBlue);
static bool ReadKeyValueInt(const char *pszValue, int &nInt);
static bool ReadKeyValueFloat(const char *pszValue, float &flFloat);
static bool ReadKeyValuePoint(const char *pszValue, Vector &Point);
static bool ReadKeyValueVector2(const char *pszValue, Vector2D &vec);
static bool ReadKeyValueVector3(const char *pszValue, Vector &vec);
static bool ReadKeyValueVector4( const char *pszValue, Vector4D &vec);
// The default chunk handler gets called before any other chunk handlers.
//
// If the handler returns ChunkFile_Ok, then it goes into the chunk.
// If the handler returns ChunkFile_NotHandled, then the chunk is
// passed to the regular handlers.
//
// If you pass NULL in here, then it disables the default chunk handler.
void SetDefaultChunkHandler( DefaultChunkHandler_t pHandler, void *pData );
void PushHandlers(CChunkHandlerMap *pHandlerMap);
void PopHandlers(void);
protected:
void BuildIndentString(char *pszDest, int nDepth);
TokenReader m_TokenReader;
FILE *m_hFile;
char m_szErrorToken[80];
char m_szIndent[MAX_INDENT_DEPTH];
int m_nCurrentDepth;
// See SetDefaultChunkHandler..
DefaultChunkHandler_t m_DefaultChunkHandler;
void *m_pDefaultChunkHandlerData;
CChunkHandlerMap *m_HandlerStack[MAX_INDENT_DEPTH];
int m_nHandlerStackDepth;
};
#endif // CHUNKFILE_H

16
public/client_class.cpp Normal file
View File

@ -0,0 +1,16 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "client_class.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
ClientClass *g_pClientClassHead=0;

180
public/client_class.h Normal file
View File

@ -0,0 +1,180 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#if !defined( CLIENT_CLASS_H )
#define CLIENT_CLASS_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
#include "dt_recv.h"
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
class Vector;
class CMouthInfo;
//-----------------------------------------------------------------------------
// represents a handle used only by the client DLL
//-----------------------------------------------------------------------------
#include "iclientrenderable.h"
#include "iclientnetworkable.h"
class ClientClass;
// Linked list of all known client classes
extern ClientClass *g_pClientClassHead;
// The serial number that gets passed in is used for ehandles.
typedef IClientNetworkable* (*CreateClientClassFn)( int entnum, int serialNum );
typedef IClientNetworkable* (*CreateEventFn)();
//-----------------------------------------------------------------------------
// Purpose: Client side class definition
//-----------------------------------------------------------------------------
class ClientClass
{
public:
ClientClass( const char *pNetworkName, CreateClientClassFn createFn, CreateEventFn createEventFn, RecvTable *pRecvTable )
{
m_pNetworkName = pNetworkName;
m_pCreateFn = createFn;
m_pCreateEventFn= createEventFn;
m_pRecvTable = pRecvTable;
// Link it in
m_pNext = g_pClientClassHead;
g_pClientClassHead = this;
}
const char* GetName()
{
return m_pNetworkName;
}
public:
CreateClientClassFn m_pCreateFn;
CreateEventFn m_pCreateEventFn; // Only called for event objects.
const char *m_pNetworkName;
RecvTable *m_pRecvTable;
ClientClass *m_pNext;
int m_ClassID; // Managed by the engine.
};
#define DECLARE_CLIENTCLASS() \
virtual int YouForgotToImplementOrDeclareClientClass();\
virtual ClientClass* GetClientClass();\
static RecvTable *m_pClassRecvTable; \
DECLARE_CLIENTCLASS_NOBASE()
// This can be used to give all datatables access to protected and private members of the class.
#define ALLOW_DATATABLES_PRIVATE_ACCESS() \
template <typename T> friend int ClientClassInit(T *);
#define DECLARE_CLIENTCLASS_NOBASE ALLOW_DATATABLES_PRIVATE_ACCESS
// This macro adds a ClientClass to the linked list in g_pClientClassHead (so
// the list can be given to the engine).
// Use this macro to expose your client class to the engine.
// networkName must match the network name of a class registered on the server.
#define IMPLEMENT_CLIENTCLASS(clientClassName, dataTable, serverClassName) \
INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName) \
static IClientNetworkable* _##clientClassName##_CreateObject( int entnum, int serialNum ) \
{ \
clientClassName *pRet = new clientClassName; \
if ( !pRet ) \
return 0; \
pRet->Init( entnum, serialNum ); \
return pRet; \
} \
ClientClass __g_##clientClassName##ClientClass(#serverClassName, \
_##clientClassName##_CreateObject, \
NULL,\
&dataTable::g_RecvTable);
// Implement a client class and provide a factory so you can allocate and delete it yourself
// (or make it a singleton).
#define IMPLEMENT_CLIENTCLASS_FACTORY(clientClassName, dataTable, serverClassName, factory) \
INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName) \
ClientClass __g_##clientClassName##ClientClass(#serverClassName, \
factory, \
NULL,\
&dataTable::g_RecvTable);
// The IMPLEMENT_CLIENTCLASS_DT macros do IMPLEMENT_CLIENT_CLASS and also do BEGIN_RECV_TABLE.
#define IMPLEMENT_CLIENTCLASS_DT(clientClassName, dataTable, serverClassName)\
IMPLEMENT_CLIENTCLASS(clientClassName, dataTable, serverClassName)\
BEGIN_RECV_TABLE(clientClassName, dataTable)
#define IMPLEMENT_CLIENTCLASS_DT_NOBASE(clientClassName, dataTable, serverClassName)\
IMPLEMENT_CLIENTCLASS(clientClassName, dataTable, serverClassName)\
BEGIN_RECV_TABLE_NOBASE(clientClassName, dataTable)
// Using IMPLEMENT_CLIENTCLASS_EVENT means the engine thinks the entity is an event so the entity
// is responsible for freeing itself.
#define IMPLEMENT_CLIENTCLASS_EVENT(clientClassName, dataTable, serverClassName)\
INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName)\
static clientClassName __g_##clientClassName; \
static IClientNetworkable* _##clientClassName##_CreateObject() {return &__g_##clientClassName;}\
ClientClass __g_##clientClassName##ClientClass(#serverClassName, \
NULL,\
_##clientClassName##_CreateObject, \
&dataTable::g_RecvTable);
#define IMPLEMENT_CLIENTCLASS_EVENT_DT(clientClassName, dataTable, serverClassName)\
namespace dataTable {extern RecvTable g_RecvTable;}\
IMPLEMENT_CLIENTCLASS_EVENT(clientClassName, dataTable, serverClassName)\
BEGIN_RECV_TABLE(clientClassName, dataTable)
// Register a client event singleton but specify a pointer to give to the engine rather than
// have a global instance. This is useful if you're using Initializers and your object's constructor
// uses some other global object (so you must use Initializers so you're constructed afterwards).
#define IMPLEMENT_CLIENTCLASS_EVENT_POINTER(clientClassName, dataTable, serverClassName, ptr)\
INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName)\
static IClientNetworkable* _##clientClassName##_CreateObject() {return ptr;}\
ClientClass __g_##clientClassName##ClientClass(#serverClassName, \
NULL,\
_##clientClassName##_CreateObject, \
&dataTable::g_RecvTable);
#define IMPLEMENT_CLIENTCLASS_EVENT_NONSINGLETON(clientClassName, dataTable, serverClassName)\
static IClientNetworkable* _##clientClassName##_CreateObject() \
{ \
clientClassName *p = new clientClassName; \
if ( p ) \
p->Init( -1, 0 ); \
return p; \
} \
ClientClass __g_##clientClassName##ClientClass(#serverClassName, \
NULL,\
_##clientClassName##_CreateObject, \
&dataTable::g_RecvTable);
// Used internally..
#define INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName) \
namespace dataTable {extern RecvTable g_RecvTable;}\
extern ClientClass __g_##clientClassName##ClientClass;\
RecvTable* clientClassName::m_pClassRecvTable = &dataTable::g_RecvTable;\
int clientClassName::YouForgotToImplementOrDeclareClientClass() {return 0;}\
ClientClass* clientClassName::GetClientClass() {return &__g_##clientClassName##ClientClass;}
#endif // CLIENT_CLASS_H

View File

@ -0,0 +1,31 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef CLIENT_RENDER_HANDLE_H
#define CLIENT_RENDER_HANDLE_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Foward declarations
//-----------------------------------------------------------------------------
class IClientRenderable;
//-----------------------------------------------------------------------------
// Handle to an renderable in the client leaf system
//-----------------------------------------------------------------------------
typedef unsigned short ClientRenderHandle_t;
enum
{
INVALID_CLIENT_RENDER_HANDLE = (ClientRenderHandle_t)0xffff,
};
#endif // CLIENT_RENDER_HANDLE_H

View File

@ -0,0 +1,33 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef CLIENT_TEXTMESSAGE_H
#define CLIENT_TEXTMESSAGE_H
#ifdef _WIN32
#pragma once
#endif
struct client_textmessage_t
{
int effect;
byte r1, g1, b1, a1; // 2 colors for effects
byte r2, g2, b2, a2;
float x;
float y;
float fadein;
float fadeout;
float holdtime;
float fxtime;
const char *pVGuiSchemeFontName; // If null, use default font for messages
const char *pName;
const char *pMessage;
bool bRoundedRectBackdropBox;
float flBoxSize; // as a function of font height
byte boxcolor[4];
char const *pClearMessage; // message to clear
};
#endif // CLIENT_TEXTMESSAGE_H

198
public/clientstats.h Normal file
View File

@ -0,0 +1,198 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#if !defined( CLIENTSTATS_H )
#define CLIENTSTATS_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
#include <limits.h>
#include "tier0/dbg.h"
#define INTERFACEVERSION_CLIENTSTATS "ClientStats004"
//-----------------------------------------------------------------------------
// An interface used to help the client stats implementation tell time
//-----------------------------------------------------------------------------
struct IClientStatsTime
{
virtual float GetTime() = 0;
};
//-----------------------------------------------------------------------------
// Allows clients to draw their own stats text, will be passed by the
// engine into DisplayStats of the IClientStats interface.
//-----------------------------------------------------------------------------
struct IClientStatsTextDisplay
{
// Draws the stats
virtual void DrawStatsText( PRINTF_FORMAT_STRING const char *fmt, ... ) = 0;
virtual void SetDrawColor( unsigned char r, unsigned char g, unsigned char b ) = 0;
// Sets a color based on a value and its max acceptable limit
virtual void SetDrawColorFromStatValues( float limit, float value ) = 0;
};
//-----------------------------------------------------------------------------
// This will exist as a singleton within the client DLL and will be hooked into
// the engine to allow clients to render their own stats.
//-----------------------------------------------------------------------------
abstract_class IClientStats
{
public:
// This is called at startup to tell the stats about time
virtual void Init( IClientStatsTime* pTime ) = 0;
// These methods are called at the beginning and the end of each run
virtual void BeginRun() = 0;
virtual void EndRun() = 0;
// These methods are called at the beginning and the end of each frame
virtual void BeginFrame() = 0;
virtual void EndFrame() = 0;
// ---------------------------------------------------------------
// All this stuff is used to prop stats for gathering r_speeds data during timedemo.
// ---------------------------------------------------------------
virtual int GetNumTimesStats( void ) const = 0;
// returns timed stats
virtual double TimedStatInFrame( int statID ) const = 0;
virtual double TotalTimedStat( int statID ) const = 0;
};
//-----------------------------------------------------------------------------
// This is a templatized implementation which can be instantiated anywhere
// Note that you still have to install it and display it though.
//-----------------------------------------------------------------------------
template <int timedStatCount, int countedStatCount>
abstract_class CBaseClientStats : public IClientStats
{
public:
void Init( IClientStatsTime* pTime );
void BeginRun();
void EndRun();
void BeginFrame();
void EndFrame();
// Timed stat gathering
void BeginTimedStat( int stat );
void EndTimedStat( int stat );
// ---------------------------------------------------------------
// All this stuff is used to prop stats for gathering r_speeds data during timedemo.
// ---------------------------------------------------------------
// returns timed stats
double TimedStatInFrame( int statID ) const
{
Assert( statID >= 0 && statID < timedStatCount );
Assert( m_StatFrameTime[statID] >= 0.0 );
return m_StatFrameTime[statID];
}
double TotalTimedStat( int statID ) const
{
Assert( statID >= 0 && statID < timedStatCount );
return m_TotalStatTime[statID];
}
virtual const char *GetCountedStatName( int statID ) const = 0;
virtual const char *GetTimedStatName( int statID ) const = 0;
protected:
// Timed statistics
double m_StatFrameTime[timedStatCount];
double m_StatStartTime[timedStatCount];
double m_TotalStatTime[timedStatCount];
private:
IClientStatsTime* m_pTime;
};
//-----------------------------------------------------------------------------
// Initializes client stats
//-----------------------------------------------------------------------------
template <int timedStatCount, int countedStatCount>
void CBaseClientStats<timedStatCount, countedStatCount>::Init( IClientStatsTime* pTime )
{
Assert( pTime );
m_pTime = pTime;
}
//-----------------------------------------------------------------------------
// These methods are called at the beginning and the end of each run
//-----------------------------------------------------------------------------
template <int timedStatCount, int countedStatCount>
void CBaseClientStats<timedStatCount, countedStatCount>::BeginRun()
{
int i;
for (i = 0; i < timedStatCount; ++i)
m_TotalStatTime[i] = 0.0;
}
template <int timedStatCount, int countedStatCount>
void CBaseClientStats<timedStatCount, countedStatCount>::EndRun()
{
}
//-----------------------------------------------------------------------------
// These methods are called at the beginning and the end of each frame
//-----------------------------------------------------------------------------
template <int timedStatCount, int countedStatCount>
void CBaseClientStats<timedStatCount, countedStatCount>::BeginFrame()
{
int i;
for (i = 0; i < timedStatCount; ++i)
m_StatFrameTime[i] = 0.0;
}
template <int timedStatCount, int countedStatCount>
void CBaseClientStats<timedStatCount, countedStatCount>::EndFrame()
{
int i;
for (i = 0; i < timedStatCount; ++i)
m_TotalStatTime[i] += m_StatFrameTime[i];
}
//-----------------------------------------------------------------------------
// Inlined stat gathering methods
//-----------------------------------------------------------------------------
template <int timedStatCount, int countedStatCount>
void CBaseClientStats<timedStatCount, countedStatCount>::BeginTimedStat( int stat )
{
if (m_pTime)
m_StatStartTime[stat] = m_pTime->GetTime();
}
template <int timedStatCount, int countedStatCount>
void CBaseClientStats<timedStatCount, countedStatCount>::EndTimedStat( int stat )
{
if (m_pTime)
m_StatFrameTime[stat] += m_pTime->GetTime() - m_StatStartTime[stat];
}
#endif // CLIENTSTATS_H

129
public/cmodel.h Normal file
View File

@ -0,0 +1,129 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef CMODEL_H
#define CMODEL_H
#ifdef _WIN32
#pragma once
#endif
#include "trace.h"
#include "tier0/dbg.h"
#include "basehandle.h"
struct edict_t;
struct model_t;
/*
==============================================================
COLLISION DETECTION
==============================================================
*/
#include "bspflags.h"
//#include "mathlib/vector.h"
// gi.BoxEdicts() can return a list of either solid or trigger entities
// FIXME: eliminate AREA_ distinction?
#define AREA_SOLID 1
#define AREA_TRIGGERS 2
#include "vcollide.h"
struct cmodel_t
{
Vector mins, maxs;
Vector origin; // for sounds or lights
int headnode;
vcollide_t vcollisionData;
};
struct csurface_t
{
const char *name;
short surfaceProps;
unsigned short flags; // BUGBUG: These are declared per surface, not per material, but this database is per-material now
};
//-----------------------------------------------------------------------------
// A ray...
//-----------------------------------------------------------------------------
struct Ray_t
{
VectorAligned m_Start; // starting point, centered within the extents
VectorAligned m_Delta; // direction + length of the ray
VectorAligned m_StartOffset; // Add this to m_Start to get the actual ray start
VectorAligned m_Extents; // Describes an axis aligned box extruded along a ray
bool m_IsRay; // are the extents zero?
bool m_IsSwept; // is delta != 0?
void Init( Vector const& start, Vector const& end )
{
Assert( &end );
VectorSubtract( end, start, m_Delta );
m_IsSwept = (m_Delta.LengthSqr() != 0);
VectorClear( m_Extents );
m_IsRay = true;
// Offset m_Start to be in the center of the box...
VectorClear( m_StartOffset );
VectorCopy( start, m_Start );
}
void Init( Vector const& start, Vector const& end, Vector const& mins, Vector const& maxs )
{
Assert( &end );
VectorSubtract( end, start, m_Delta );
m_IsSwept = (m_Delta.LengthSqr() != 0);
VectorSubtract( maxs, mins, m_Extents );
m_Extents *= 0.5f;
m_IsRay = (m_Extents.LengthSqr() < 1e-6);
// Offset m_Start to be in the center of the box...
VectorAdd( mins, maxs, m_StartOffset );
m_StartOffset *= 0.5f;
VectorAdd( start, m_StartOffset, m_Start );
m_StartOffset *= -1.0f;
}
// compute inverse delta
Vector InvDelta() const
{
Vector vecInvDelta;
for ( int iAxis = 0; iAxis < 3; ++iAxis )
{
if ( m_Delta[iAxis] != 0.0f )
{
vecInvDelta[iAxis] = 1.0f / m_Delta[iAxis];
}
else
{
vecInvDelta[iAxis] = FLT_MAX;
}
}
return vecInvDelta;
}
private:
};
#endif // CMODEL_H
#include "gametrace.h"

3262
public/collisionutils.cpp Normal file

File diff suppressed because it is too large Load Diff

450
public/collisionutils.h Normal file
View File

@ -0,0 +1,450 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Common collision utility methods
//
// $Header: $
// $NoKeywords: $
//=============================================================================//
#ifndef COLLISIONUTILS_H
#define COLLISIONUTILS_H
#include "tier0/platform.h"
#ifdef _WIN32
#pragma once
#endif
#include "mathlib/ssemath.h"
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
struct Ray_t;
class Vector;
class Vector2D;
class Vector4D;
struct cplane_t;
class QAngle;
class CBaseTrace;
struct matrix3x4_t;
//-----------------------------------------------------------------------------
//
// IntersectRayWithTriangle
//
// Intersects a ray with a triangle, returns distance t along ray.
// t will be less than zero if no intersection occurred
// oneSided will cull collisions which approach the triangle from the back
// side, assuming the vertices are specified in counter-clockwise order
// The vertices need not be specified in that order if oneSided is not used
//
//-----------------------------------------------------------------------------
float IntersectRayWithTriangle( const Ray_t& ray,
const Vector& v1, const Vector& v2, const Vector& v3,
bool oneSided );
//-----------------------------------------------------------------------------
//
// ComputeIntersectionBarycentricCoordinates
//
// Figures out the barycentric coordinates (u,v) where a ray hits a
// triangle. Note that this will ignore the ray extents, and it also ignores
// the ray length. Note that the edge from v1->v2 represents u (v2: u = 1),
// and the edge from v1->v3 represents v (v3: v = 1). It returns false
// if the ray is parallel to the triangle (or when t is specified if t is less
// than zero).
//
//-----------------------------------------------------------------------------
bool ComputeIntersectionBarycentricCoordinates( const Ray_t& ray,
const Vector& v1, const Vector& v2, const Vector& v3, float& u, float& v,
float *t = 0 );
//-----------------------------------------------------------------------------
//
// IntersectRayWithRay
//
// Returns whether or not there was an intersection. The "t" paramter is the
// distance along ray0 and the "s" parameter is the distance along ray1. If
// the two lines to not intersect the "t" and "s" represent the closest approach.
// "t" and "s" will not change if the rays are parallel.
//
//-----------------------------------------------------------------------------
bool IntersectRayWithRay( const Ray_t &ray0, const Ray_t &ray1, float &t, float &s );
//-----------------------------------------------------------------------------
//
// IntersectRayWithSphere
//
// Returns whether or not there was an intersection. Returns the two intersection points.
// NOTE: The point of closest approach can be found at the average t value.
//
//-----------------------------------------------------------------------------
bool IntersectRayWithSphere( const Vector &vecRayOrigin, const Vector &vecRayDelta, const Vector &vecSphereCenter, float flRadius, float *pT1, float *pT2 );
//-----------------------------------------------------------------------------
//
// IntersectInfiniteRayWithSphere
//
// Returns whether or not there was an intersection of a sphere against an infinitely
// extending ray.
// Returns the two intersection points
//
//-----------------------------------------------------------------------------
bool IntersectInfiniteRayWithSphere( const Vector &vecRayOrigin, const Vector &vecRayDelta,
const Vector &vecSphereCenter, float flRadius, float *pT1, float *pT2 );
// returns true if the sphere and cone intersect
// NOTE: cone sine/cosine are the half angle of the cone
bool IsSphereIntersectingCone( const Vector &sphereCenter, float sphereRadius, const Vector &coneOrigin, const Vector &coneNormal, float coneSine, float coneCosine );
//-----------------------------------------------------------------------------
//
// IntersectRayWithPlane
//
// Intersects a ray with a plane, returns distance t along ray.
// t will be less than zero the intersection occurs in the opposite direction of the ray.
//
//-----------------------------------------------------------------------------
float IntersectRayWithPlane( const Ray_t& ray, const cplane_t& plane );
float IntersectRayWithPlane( const Vector& org, const Vector& dir, const cplane_t& plane );
float IntersectRayWithPlane( const Vector& org, const Vector& dir, const Vector& normal, float dist );
// This version intersects a ray with an axis-aligned plane
float IntersectRayWithAAPlane( const Vector& vecStart, const Vector& vecEnd, int nAxis, float flSign, float flDist );
//-----------------------------------------------------------------------------
// IntersectRayWithBox
//
// Purpose: Computes the intersection of a ray with a box (AABB)
// Output : Returns true if there is an intersection + trace information
//-----------------------------------------------------------------------------
bool IntersectRayWithBox( const Vector &rayStart, const Vector &rayDelta, const Vector &boxMins, const Vector &boxMaxs, float epsilon, CBaseTrace *pTrace, float *pFractionLeftSolid = NULL );
bool IntersectRayWithBox( const Ray_t &ray, const Vector &boxMins, const Vector &boxMaxs, float epsilon, CBaseTrace *pTrace, float *pFractionLeftSolid = NULL );
//-----------------------------------------------------------------------------
// Intersects a ray against a box
//-----------------------------------------------------------------------------
struct BoxTraceInfo_t
{
float t1;
float t2;
int hitside;
bool startsolid;
};
bool IntersectRayWithBox( const Vector &vecRayStart, const Vector &vecRayDelta,
const Vector &boxMins, const Vector &boxMaxs, float flTolerance, BoxTraceInfo_t *pTrace );
//-----------------------------------------------------------------------------
// IntersectRayWithOBB
//
// Purpose: Computes the intersection of a ray with a oriented box (OBB)
// Output : Returns true if there is an intersection + trace information
//-----------------------------------------------------------------------------
bool IntersectRayWithOBB( const Vector &vecRayStart, const Vector &vecRayDelta,
const matrix3x4_t &matOBBToWorld, const Vector &vecOBBMins, const Vector &vecOBBMaxs,
float flTolerance, CBaseTrace *pTrace );
bool IntersectRayWithOBB( const Vector &vecRayOrigin, const Vector &vecRayDelta,
const Vector &vecBoxOrigin, const QAngle &angBoxRotation,
const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace );
bool IntersectRayWithOBB( const Ray_t &ray, const Vector &vecBoxOrigin, const QAngle &angBoxRotation,
const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace );
bool IntersectRayWithOBB( const Ray_t &ray, const matrix3x4_t &matOBBToWorld,
const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace );
bool IntersectRayWithOBB( const Vector &vecRayStart, const Vector &vecRayDelta,
const matrix3x4_t &matOBBToWorld, const Vector &vecOBBMins, const Vector &vecOBBMaxs,
float flTolerance, BoxTraceInfo_t *pTrace );
//-----------------------------------------------------------------------------
//
// IsSphereIntersectingSphere
//
// returns true if there's an intersection between sphere and sphere
//
//-----------------------------------------------------------------------------
bool IsSphereIntersectingSphere( const Vector& center1, float radius1,
const Vector& center2, float radius2 );
//-----------------------------------------------------------------------------
//
// IsBoxIntersectingSphere
//
// returns true if there's an intersection between box and sphere
//
//-----------------------------------------------------------------------------
bool IsBoxIntersectingSphere( const Vector& boxMin, const Vector& boxMax,
const Vector& center, float radius );
bool IsBoxIntersectingSphereExtents( const Vector& boxCenter, const Vector& boxHalfDiag,
const Vector& center, float radius );
//-----------------------------------------------------------------------------
// returns true if there's an intersection between ray and sphere
//-----------------------------------------------------------------------------
bool IsRayIntersectingSphere( const Vector &vecRayOrigin, const Vector &vecRayDelta,
const Vector &vecSphereCenter, float flRadius, float flTolerance = 0.0f );
//-----------------------------------------------------------------------------
//
// IsCircleIntersectingRectangle
//
// returns true if there's an intersection between rectangle and circle
//
//-----------------------------------------------------------------------------
bool IsCircleIntersectingRectangle( const Vector2D& boxMin, const Vector2D& boxMax,
const Vector2D& center, float radius );
//-----------------------------------------------------------------------------
//
// IsBoxIntersectingBox
//
// returns true if there's an intersection between two boxes
//
//-----------------------------------------------------------------------------
bool IsBoxIntersectingBox( const Vector& boxMin1, const Vector& boxMax1,
const Vector& boxMin2, const Vector& boxMax2 );
bool IsBoxIntersectingBoxExtents( const Vector& boxCenter1, const Vector& boxHalfDiagonal1,
const Vector& boxCenter2, const Vector& boxHalfDiagonal2 );
#ifdef _X360
// inline version:
#include "mathlib/ssemath.h"
inline bool IsBoxIntersectingBoxExtents( const fltx4 boxCenter1, const fltx4 boxHalfDiagonal1,
const fltx4 boxCenter2, const fltx4 boxHalfDiagonal2 );
#endif
//-----------------------------------------------------------------------------
//
// IsOBBIntersectingOBB
//
// returns true if there's an intersection between two OBBs
//
//-----------------------------------------------------------------------------
bool IsOBBIntersectingOBB( const Vector &vecOrigin1, const QAngle &vecAngles1, const Vector& boxMin1, const Vector& boxMax1,
const Vector &vecOrigin2, const QAngle &vecAngles2, const Vector& boxMin2, const Vector& boxMax2, float flTolerance = 0.0f );
//-----------------------------------------------------------------------------
//
// IsBoxIntersectingRay
//
// returns true if there's an intersection between box and ray
//
//-----------------------------------------------------------------------------
bool FASTCALL IsBoxIntersectingRay( const Vector& boxMin, const Vector& boxMax,
const Vector& origin, const Vector& delta, float flTolerance = 0.0f );
bool FASTCALL IsBoxIntersectingRay( const Vector& boxMin, const Vector& boxMax,
const Ray_t& ray, float flTolerance = 0.0f );
bool FASTCALL IsBoxIntersectingRay( const Vector& boxMin, const Vector& boxMax,
const Vector& origin, const Vector& delta,
const Vector& invDelta, float flTolerance = 0.0f );
// On the PC, we can't pass fltx4's in registers like this. On the x360, it is
// much better if we do.
#ifdef _X360
bool FASTCALL IsBoxIntersectingRay( fltx4 boxMin, fltx4 boxMax,
fltx4 origin, fltx4 delta, fltx4 invDelta, // ray parameters
fltx4 vTolerance = LoadZeroSIMD() ///< eg from ReplicateX4(flTolerance)
);
#else
bool FASTCALL IsBoxIntersectingRay( const fltx4 &boxMin, const fltx4 &boxMax,
const fltx4 & origin, const fltx4 & delta, const fltx4 & invDelta, // ray parameters
const fltx4 & vTolerance = Four_Zeros ///< eg from ReplicateX4(flTolerance)
);
#endif
bool inline FASTCALL IsBoxIntersectingRay( const fltx4& boxMin, const fltx4& boxMax,
const fltx4& origin, const fltx4& delta, float flTolerance = 0.0f )
{
return IsBoxIntersectingRay( boxMin, boxMax, origin, delta, ReciprocalSIMD(delta), ReplicateX4(flTolerance) );
}
bool FASTCALL IsBoxIntersectingRay( const fltx4& boxMin, const fltx4& boxMax,
const Ray_t& ray, float flTolerance = 0.0f );
//-----------------------------------------------------------------------------
//
// IsPointInBox
//
// returns true if the point is in the box
//
//-----------------------------------------------------------------------------
bool IsPointInBox( const Vector& pt, const Vector& boxMin, const Vector& boxMax );
// SIMD version
FORCEINLINE bool IsPointInBox( const fltx4& pt, const fltx4& boxMin, const fltx4& boxMax )
{
fltx4 greater = CmpGtSIMD( pt,boxMax );
fltx4 less = CmpLtSIMD( pt, boxMin );
return (IsAllZeros(SetWToZeroSIMD(OrSIMD(greater,less))));
}
//-----------------------------------------------------------------------------
// Purpose: returns true if pt intersects the truncated cone
// origin - cone tip, axis unit cone axis, cosAngle - cosine of cone axis to surface angle
//-----------------------------------------------------------------------------
bool IsPointInCone( const Vector &pt, const Vector &origin, const Vector &axis, float cosAngle, float length );
//-----------------------------------------------------------------------------
// Intersects a plane with a triangle (using barycentric definition)
// The return value, in pIntersection, is an array of barycentric coordinates
// describing at most 2 intersection points.
// The return value is the number of intersection points
//-----------------------------------------------------------------------------
int IntersectTriangleWithPlaneBarycentric( const Vector& org, const Vector& edgeU, const Vector& edgeV,
const Vector4D& plane, Vector2D* pIntersection );
//-----------------------------------------------------------------------------
//
// PointInQuadBarycentric
//
// Given a point and a quad in a plane return the u and v (barycentric) positions
// of the point relative to the quad. The points (v1,v2,v3,v4) should be given
// in a counter-clockwise order with v1 acting as the primary corner (u=0, v=0).
// Thus, u0 = v2 - v1, and v0 = v4 - v1.
//
//-----------------------------------------------------------------------------
enum QuadBarycentricRetval_t
{
BARY_QUADRATIC_FALSE = 0,
BARY_QUADRATIC_TRUE = 1,
BARY_QUADRATIC_NEGATIVE_DISCRIMINANT = 2
};
QuadBarycentricRetval_t PointInQuadToBarycentric( const Vector &v1, const Vector &v2,
const Vector &v3, const Vector &v4, const Vector &point, Vector2D &uv );
void PointInQuadFromBarycentric( const Vector &v1, const Vector &v2, const Vector &v3, const Vector &v4,
const Vector2D &uv, Vector &point );
void TexCoordInQuadFromBarycentric( const Vector2D &v1, const Vector2D &v2, const Vector2D &v3, const Vector2D &v4,
const Vector2D &uv, Vector2D &texCoord );
//-----------------------------------------------------------------------------
// Compute point from barycentric specification
// Edge u goes from v0 to v1, edge v goes from v0 to v2
//-----------------------------------------------------------------------------
void ComputePointFromBarycentric( const Vector& v0, const Vector& v1, const Vector& v2,
float u, float v, Vector& pt );
void ComputePointFromBarycentric( const Vector2D& v0, const Vector2D& v1, const Vector2D& v2,
float u, float v, Vector2D& pt );
//-----------------------------------------------------------------------------
// Swept OBB test
//-----------------------------------------------------------------------------
bool IsRayIntersectingOBB( const Ray_t &ray, const Vector& org, const QAngle& angles,
const Vector& mins, const Vector& maxs );
//-----------------------------------------------------------------------------
// Compute a separating plane between two boxes (expensive!)
// Returns false if no separating plane exists
//-----------------------------------------------------------------------------
bool ComputeSeparatingPlane( const Vector& org1, const QAngle& angles1, const Vector& min1, const Vector& max1,
const Vector& org2, const QAngle& angles2, const Vector& min2, const Vector& max2,
float tolerance, cplane_t* pPlane );
//-----------------------------------------------------------------------------
// IsBoxIntersectingTriangle
//
// Test for an intersection (overlap) between an axial-aligned bounding
// box (AABB) and a triangle.
//
// Triangle points are in counter-clockwise order with the normal facing "out."
//
// Using the "Separating-Axis Theorem" to test for intersections between
// a triangle and an axial-aligned bounding box (AABB).
// 1. 3 Axis Plane Tests - x, y, z
// 2. 9 Edge Planes Tests - the 3 edges of the triangle crossed with all 3 axial
// planes (x, y, z)
// 3. 1 Face Plane Test - the plane the triangle resides in (cplane_t plane)
//-----------------------------------------------------------------------------
bool IsBoxIntersectingTriangle( const Vector &vecBoxCenter, const Vector &vecBoxExtents,
const Vector &v1, const Vector &v2, const Vector &v3,
const cplane_t &plane, float flTolerance );
Vector CalcClosestPointOnTriangle( const Vector &P, const Vector &v0, const Vector &v1, const Vector &v2 );
//-----------------------------------------------------------------------------
// Compute if the OBB intersects the quad plane, and whether the entire
// OBB/Quad intersection is contained within the quad itself
//
// False if no intersection exists, or if part of the intersection is
// outside the quad's extents
//-----------------------------------------------------------------------------
bool OBBHasFullyContainedIntersectionWithQuad( const Vector &vOBBExtent1_Scaled, const Vector &vOBBExtent2_Scaled, const Vector &vOBBExtent3_Scaled, const Vector &ptOBBCenter,
const Vector &vQuadNormal, float fQuadPlaneDist, const Vector &ptQuadCenter,
const Vector &vQuadExtent1_Normalized, float fQuadExtent1Length,
const Vector &vQuadExtent2_Normalized, float fQuadExtent2Length );
//-----------------------------------------------------------------------------
// Compute if the Ray intersects the quad plane, and whether the entire
// Ray/Quad intersection is contained within the quad itself
//
// False if no intersection exists, or if part of the intersection is
// outside the quad's extents
//-----------------------------------------------------------------------------
bool RayHasFullyContainedIntersectionWithQuad( const Ray_t &ray,
const Vector &vQuadNormal, float fQuadPlaneDist, const Vector &ptQuadCenter,
const Vector &vQuadExtent1_Normalized, float fQuadExtent1Length,
const Vector &vQuadExtent2_Normalized, float fQuadExtent2Length );
//-----------------------------------------------------------------------------
// INLINES
//-----------------------------------------------------------------------------
#ifdef _X360
inline bool IsBoxIntersectingBoxExtents( const fltx4 boxCenter1, const fltx4 boxHalfDiagonal1,
const fltx4 boxCenter2, const fltx4 boxHalfDiagonal2 )
{
fltx4 vecDelta, vecSize;
vecDelta = SubSIMD(boxCenter1, boxCenter2);
vecSize = AddSIMD(boxHalfDiagonal1, boxHalfDiagonal2);
uint condition;
XMVectorInBoundsR(&condition, vecDelta, vecSize);
// we want the top three words to be all 1's ; that means in bounds
return XMComparisonAllInBounds( condition );
}
#endif
#endif // COLLISIONUTILS_H

31
public/con_nprint.h Normal file
View File

@ -0,0 +1,31 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Debug overlay / notfication printing
//
//=============================================================================//
#ifndef CON_NPRINT_H
#define CON_NPRINT_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose: Debug overlay / notfication printing
// NOTE: Structure cannot be changed by mods
//-----------------------------------------------------------------------------
typedef struct con_nprint_s
{
int index; // Row #
float time_to_live; // # of seconds before it disappears. -1 means to display for 1 frame then go away.
float color[ 3 ]; // RGB colors ( 0.0 -> 1.0 scale )
bool fixed_width_font;
} con_nprint_t;
// Print string on line idx
void Con_NPrintf( int idx, PRINTF_FORMAT_STRING const char *fmt, ... );
// Customized printout
void Con_NXPrintf( const con_nprint_t *info, PRINTF_FORMAT_STRING const char *fmt, ... );
#endif // CON_NPRINT_H

439
public/const.h Normal file
View File

@ -0,0 +1,439 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef CONST_H
#define CONST_H
#ifdef _WIN32
#pragma once
#endif
// the command line param that tells the engine to use steam
#define STEAM_PARM "-steam"
// the command line param to tell dedicated server to restart
// if they are out of date
#define AUTO_RESTART "-autoupdate"
// the message a server sends when a clients steam login is expired
#define INVALID_STEAM_TICKET "Invalid STEAM UserID Ticket\n"
#define INVALID_STEAM_VACBANSTATE "VAC banned from secure server\n"
#define INVALID_STEAM_LOGGED_IN_ELSEWHERE "This Steam account is being used in another location\n"
#define INVALID_STEAM_LOGON_NOT_CONNECTED "Client not connected to Steam\n"
#define INVALID_STEAM_LOGON_TICKET_CANCELED "Client left game (Steam auth ticket has been canceled)\n"
#define CLIENTNAME_TIMED_OUT "%s timed out"
// This is the default, see shareddefs.h for mod-specific value, which can override this
#define DEFAULT_TICK_INTERVAL (0.015) // 15 msec is the default
#define MINIMUM_TICK_INTERVAL (0.001)
#define MAXIMUM_TICK_INTERVAL (0.1)
// This is the max # of players the engine can handle
#define ABSOLUTE_PLAYER_LIMIT 255 // not 256, so we can send the limit as a byte
#define ABSOLUTE_PLAYER_LIMIT_DW ( (ABSOLUTE_PLAYER_LIMIT/32) + 1 )
// a player name may have 31 chars + 0 on the PC.
// the 360 only allows 15 char + 0, but stick with the larger PC size for cross-platform communication
#define MAX_PLAYER_NAME_LENGTH 32
#ifdef _X360
#define MAX_PLAYERS_PER_CLIENT XUSER_MAX_COUNT // Xbox 360 supports 4 players per console
#else
#define MAX_PLAYERS_PER_CLIENT 1 // One player per PC
#endif
#define MAX_MAP_NAME 32
#define MAX_NETWORKID_LENGTH 64 // num chars for a network (i.e steam) ID
// BUGBUG: Reconcile with or derive this from the engine's internal definition!
// FIXME: I added an extra bit because I needed to make it signed
#define SP_MODEL_INDEX_BITS 12
// How many bits to use to encode an edict.
#define MAX_EDICT_BITS 11 // # of bits needed to represent max edicts
// Max # of edicts in a level
#define MAX_EDICTS (1<<MAX_EDICT_BITS)
// How many bits to use to encode an server class index
#define MAX_SERVER_CLASS_BITS 9
// Max # of networkable server classes
#define MAX_SERVER_CLASSES (1<<MAX_SERVER_CLASS_BITS)
#define SIGNED_GUID_LEN 32 // Hashed CD Key (32 hex alphabetic chars + 0 terminator )
// Used for networking ehandles.
#define NUM_ENT_ENTRY_BITS (MAX_EDICT_BITS + 1)
#define NUM_ENT_ENTRIES (1 << NUM_ENT_ENTRY_BITS)
#define ENT_ENTRY_MASK (NUM_ENT_ENTRIES - 1)
#define INVALID_EHANDLE_INDEX 0xFFFFFFFF
#define NUM_SERIAL_NUM_BITS (32 - NUM_ENT_ENTRY_BITS)
// Networked ehandles use less bits to encode the serial number.
#define NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS 10
#define NUM_NETWORKED_EHANDLE_BITS (MAX_EDICT_BITS + NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS)
#define INVALID_NETWORKED_EHANDLE_VALUE ((1 << NUM_NETWORKED_EHANDLE_BITS) - 1)
// This is the maximum amount of data a PackedEntity can have. Having a limit allows us
// to use static arrays sometimes instead of allocating memory all over the place.
#define MAX_PACKEDENTITY_DATA (16384)
// This is the maximum number of properties that can be delta'd. Must be evenly divisible by 8.
#define MAX_PACKEDENTITY_PROPS (4096)
// a client can have up to 4 customization files (logo, sounds, models, txt).
#define MAX_CUSTOM_FILES 4 // max 4 files
#define MAX_CUSTOM_FILE_SIZE 524288 // Half a megabyte
//
// Constants shared by the engine and dlls
// This header file included by engine files and DLL files.
// Most came from server.h
// CBaseEntity::m_fFlags
// PLAYER SPECIFIC FLAGS FIRST BECAUSE WE USE ONLY A FEW BITS OF NETWORK PRECISION
// This top block is for singleplayer games only....no HL2:DM (which defines HL2_DLL)
#if !defined( HL2MP ) && ( defined( PORTAL ) || defined( HL2_EPISODIC ) || defined ( HL2_DLL ) || defined( HL2_LOSTCOAST ) )
#define FL_ONGROUND (1<<0) // At rest / on the ground
#define FL_DUCKING (1<<1) // Player flag -- Player is fully crouched
#define FL_WATERJUMP (1<<2) // player jumping out of water
#define FL_ONTRAIN (1<<3) // Player is _controlling_ a train, so movement commands should be ignored on client during prediction.
#define FL_INRAIN (1<<4) // Indicates the entity is standing in rain
#define FL_FROZEN (1<<5) // Player is frozen for 3rd person camera
#define FL_ATCONTROLS (1<<6) // Player can't move, but keeps key inputs for controlling another entity
#define FL_CLIENT (1<<7) // Is a player
#define FL_FAKECLIENT (1<<8) // Fake client, simulated server side; don't send network messages to them
// NON-PLAYER SPECIFIC (i.e., not used by GameMovement or the client .dll ) -- Can still be applied to players, though
#define FL_INWATER (1<<9) // In water
// NOTE if you move things up, make sure to change this value
#define PLAYER_FLAG_BITS 10
#define FL_FLY (1<<10) // Changes the SV_Movestep() behavior to not need to be on ground
#define FL_SWIM (1<<11) // Changes the SV_Movestep() behavior to not need to be on ground (but stay in water)
#define FL_CONVEYOR (1<<12)
#define FL_NPC (1<<13)
#define FL_GODMODE (1<<14)
#define FL_NOTARGET (1<<15)
#define FL_AIMTARGET (1<<16) // set if the crosshair needs to aim onto the entity
#define FL_PARTIALGROUND (1<<17) // not all corners are valid
#define FL_STATICPROP (1<<18) // Eetsa static prop!
#define FL_GRAPHED (1<<19) // worldgraph has this ent listed as something that blocks a connection
#define FL_GRENADE (1<<20)
#define FL_STEPMOVEMENT (1<<21) // Changes the SV_Movestep() behavior to not do any processing
#define FL_DONTTOUCH (1<<22) // Doesn't generate touch functions, generates Untouch() for anything it was touching when this flag was set
#define FL_BASEVELOCITY (1<<23) // Base velocity has been applied this frame (used to convert base velocity into momentum)
#define FL_WORLDBRUSH (1<<24) // Not moveable/removeable brush entity (really part of the world, but represented as an entity for transparency or something)
#define FL_OBJECT (1<<25) // Terrible name. This is an object that NPCs should see. Missiles, for example.
#define FL_KILLME (1<<26) // This entity is marked for death -- will be freed by game DLL
#define FL_ONFIRE (1<<27) // You know...
#define FL_DISSOLVING (1<<28) // We're dissolving!
#define FL_TRANSRAGDOLL (1<<29) // In the process of turning into a client side ragdoll.
#define FL_UNBLOCKABLE_BY_PLAYER (1<<30) // pusher that can't be blocked by the player
#else
#define FL_ONGROUND (1<<0) // At rest / on the ground
#define FL_DUCKING (1<<1) // Player flag -- Player is fully crouched
#define FL_ANIMDUCKING (1<<2) // Player flag -- Player is in the process of crouching or uncrouching but could be in transition
// examples: Fully ducked: FL_DUCKING & FL_ANIMDUCKING
// Previously fully ducked, unducking in progress: FL_DUCKING & !FL_ANIMDUCKING
// Fully unducked: !FL_DUCKING & !FL_ANIMDUCKING
// Previously fully unducked, ducking in progress: !FL_DUCKING & FL_ANIMDUCKING
#define FL_WATERJUMP (1<<3) // player jumping out of water
#define FL_ONTRAIN (1<<4) // Player is _controlling_ a train, so movement commands should be ignored on client during prediction.
#define FL_INRAIN (1<<5) // Indicates the entity is standing in rain
#define FL_FROZEN (1<<6) // Player is frozen for 3rd person camera
#define FL_ATCONTROLS (1<<7) // Player can't move, but keeps key inputs for controlling another entity
#define FL_CLIENT (1<<8) // Is a player
#define FL_FAKECLIENT (1<<9) // Fake client, simulated server side; don't send network messages to them
// NON-PLAYER SPECIFIC (i.e., not used by GameMovement or the client .dll ) -- Can still be applied to players, though
#define FL_INWATER (1<<10) // In water
// NOTE if you move things up, make sure to change this value
#define PLAYER_FLAG_BITS 11
#define FL_FLY (1<<11) // Changes the SV_Movestep() behavior to not need to be on ground
#define FL_SWIM (1<<12) // Changes the SV_Movestep() behavior to not need to be on ground (but stay in water)
#define FL_CONVEYOR (1<<13)
#define FL_NPC (1<<14)
#define FL_GODMODE (1<<15)
#define FL_NOTARGET (1<<16)
#define FL_AIMTARGET (1<<17) // set if the crosshair needs to aim onto the entity
#define FL_PARTIALGROUND (1<<18) // not all corners are valid
#define FL_STATICPROP (1<<19) // Eetsa static prop!
#define FL_GRAPHED (1<<20) // worldgraph has this ent listed as something that blocks a connection
#define FL_GRENADE (1<<21)
#define FL_STEPMOVEMENT (1<<22) // Changes the SV_Movestep() behavior to not do any processing
#define FL_DONTTOUCH (1<<23) // Doesn't generate touch functions, generates Untouch() for anything it was touching when this flag was set
#define FL_BASEVELOCITY (1<<24) // Base velocity has been applied this frame (used to convert base velocity into momentum)
#define FL_WORLDBRUSH (1<<25) // Not moveable/removeable brush entity (really part of the world, but represented as an entity for transparency or something)
#define FL_OBJECT (1<<26) // Terrible name. This is an object that NPCs should see. Missiles, for example.
#define FL_KILLME (1<<27) // This entity is marked for death -- will be freed by game DLL
#define FL_ONFIRE (1<<28) // You know...
#define FL_DISSOLVING (1<<29) // We're dissolving!
#define FL_TRANSRAGDOLL (1<<30) // In the process of turning into a client side ragdoll.
#define FL_UNBLOCKABLE_BY_PLAYER (1<<31) // pusher that can't be blocked by the player
#endif
// edict->movetype values
enum MoveType_t
{
MOVETYPE_NONE = 0, // never moves
MOVETYPE_ISOMETRIC, // For players -- in TF2 commander view, etc.
MOVETYPE_WALK, // Player only - moving on the ground
MOVETYPE_STEP, // gravity, special edge handling -- monsters use this
MOVETYPE_FLY, // No gravity, but still collides with stuff
MOVETYPE_FLYGRAVITY, // flies through the air + is affected by gravity
MOVETYPE_VPHYSICS, // uses VPHYSICS for simulation
MOVETYPE_PUSH, // no clip to world, push and crush
MOVETYPE_NOCLIP, // No gravity, no collisions, still do velocity/avelocity
MOVETYPE_LADDER, // Used by players only when going onto a ladder
MOVETYPE_OBSERVER, // Observer movement, depends on player's observer mode
MOVETYPE_CUSTOM, // Allows the entity to describe its own physics
// should always be defined as the last item in the list
MOVETYPE_LAST = MOVETYPE_CUSTOM,
MOVETYPE_MAX_BITS = 4
};
// edict->movecollide values
enum MoveCollide_t
{
MOVECOLLIDE_DEFAULT = 0,
// These ones only work for MOVETYPE_FLY + MOVETYPE_FLYGRAVITY
MOVECOLLIDE_FLY_BOUNCE, // bounces, reflects, based on elasticity of surface and object - applies friction (adjust velocity)
MOVECOLLIDE_FLY_CUSTOM, // Touch() will modify the velocity however it likes
MOVECOLLIDE_FLY_SLIDE, // slides along surfaces (no bounce) - applies friciton (adjusts velocity)
MOVECOLLIDE_COUNT, // Number of different movecollides
// When adding new movecollide types, make sure this is correct
MOVECOLLIDE_MAX_BITS = 3
};
// edict->solid values
// NOTE: Some movetypes will cause collisions independent of SOLID_NOT/SOLID_TRIGGER when the entity moves
// SOLID only effects OTHER entities colliding with this one when they move - UGH!
// Solid type basically describes how the bounding volume of the object is represented
// NOTE: SOLID_BBOX MUST BE 2, and SOLID_VPHYSICS MUST BE 6
// NOTE: These numerical values are used in the FGD by the prop code (see prop_dynamic)
enum SolidType_t
{
SOLID_NONE = 0, // no solid model
SOLID_BSP = 1, // a BSP tree
SOLID_BBOX = 2, // an AABB
SOLID_OBB = 3, // an OBB (not implemented yet)
SOLID_OBB_YAW = 4, // an OBB, constrained so that it can only yaw
SOLID_CUSTOM = 5, // Always call into the entity for tests
SOLID_VPHYSICS = 6, // solid vphysics object, get vcollide from the model and collide with that
SOLID_LAST,
};
enum SolidFlags_t
{
FSOLID_CUSTOMRAYTEST = 0x0001, // Ignore solid type + always call into the entity for ray tests
FSOLID_CUSTOMBOXTEST = 0x0002, // Ignore solid type + always call into the entity for swept box tests
FSOLID_NOT_SOLID = 0x0004, // Are we currently not solid?
FSOLID_TRIGGER = 0x0008, // This is something may be collideable but fires touch functions
// even when it's not collideable (when the FSOLID_NOT_SOLID flag is set)
FSOLID_NOT_STANDABLE = 0x0010, // You can't stand on this
FSOLID_VOLUME_CONTENTS = 0x0020, // Contains volumetric contents (like water)
FSOLID_FORCE_WORLD_ALIGNED = 0x0040, // Forces the collision rep to be world-aligned even if it's SOLID_BSP or SOLID_VPHYSICS
FSOLID_USE_TRIGGER_BOUNDS = 0x0080, // Uses a special trigger bounds separate from the normal OBB
FSOLID_ROOT_PARENT_ALIGNED = 0x0100, // Collisions are defined in root parent's local coordinate space
FSOLID_TRIGGER_TOUCH_DEBRIS = 0x0200, // This trigger will touch debris objects
FSOLID_MAX_BITS = 10
};
//-----------------------------------------------------------------------------
// A couple of inline helper methods
//-----------------------------------------------------------------------------
inline bool IsSolid( SolidType_t solidType, int nSolidFlags )
{
return (solidType != SOLID_NONE) && ((nSolidFlags & FSOLID_NOT_SOLID) == 0);
}
// m_lifeState values
#define LIFE_ALIVE 0 // alive
#define LIFE_DYING 1 // playing death animation or still falling off of a ledge waiting to hit ground
#define LIFE_DEAD 2 // dead. lying still.
#define LIFE_RESPAWNABLE 3
#define LIFE_DISCARDBODY 4
// entity effects
enum
{
EF_BONEMERGE = 0x001, // Performs bone merge on client side
EF_BRIGHTLIGHT = 0x002, // DLIGHT centered at entity origin
EF_DIMLIGHT = 0x004, // player flashlight
EF_NOINTERP = 0x008, // don't interpolate the next frame
EF_NOSHADOW = 0x010, // Don't cast no shadow
EF_NODRAW = 0x020, // don't draw entity
EF_NORECEIVESHADOW = 0x040, // Don't receive no shadow
EF_BONEMERGE_FASTCULL = 0x080, // For use with EF_BONEMERGE. If this is set, then it places this ent's origin at its
// parent and uses the parent's bbox + the max extents of the aiment.
// Otherwise, it sets up the parent's bones every frame to figure out where to place
// the aiment, which is inefficient because it'll setup the parent's bones even if
// the parent is not in the PVS.
EF_ITEM_BLINK = 0x100, // blink an item so that the user notices it.
EF_PARENT_ANIMATES = 0x200, // always assume that the parent entity is animating
EF_MAX_BITS = 10
};
#define EF_PARITY_BITS 3
#define EF_PARITY_MASK ((1<<EF_PARITY_BITS)-1)
// How many bits does the muzzle flash parity thing get?
#define EF_MUZZLEFLASH_BITS 2
// plats
#define PLAT_LOW_TRIGGER 1
// Trains
#define SF_TRAIN_WAIT_RETRIGGER 1
#define SF_TRAIN_PASSABLE 8 // Train is not solid -- used to make water trains
// view angle update types for CPlayerState::fixangle
#define FIXANGLE_NONE 0
#define FIXANGLE_ABSOLUTE 1
#define FIXANGLE_RELATIVE 2
// Break Model Defines
#define BREAK_GLASS 0x01
#define BREAK_METAL 0x02
#define BREAK_FLESH 0x04
#define BREAK_WOOD 0x08
#define BREAK_SMOKE 0x10
#define BREAK_TRANS 0x20
#define BREAK_CONCRETE 0x40
// If this is set, then we share a lighting origin with the last non-slave breakable sent down to the client
#define BREAK_SLAVE 0x80
// Colliding temp entity sounds
#define BOUNCE_GLASS BREAK_GLASS
#define BOUNCE_METAL BREAK_METAL
#define BOUNCE_FLESH BREAK_FLESH
#define BOUNCE_WOOD BREAK_WOOD
#define BOUNCE_SHRAP 0x10
#define BOUNCE_SHELL 0x20
#define BOUNCE_CONCRETE BREAK_CONCRETE
#define BOUNCE_SHOTSHELL 0x80
// Temp entity bounce sound types
#define TE_BOUNCE_NULL 0
#define TE_BOUNCE_SHELL 1
#define TE_BOUNCE_SHOTSHELL 2
// Rendering constants
// if this is changed, update common/MaterialSystem/Sprite.cpp
enum RenderMode_t
{
kRenderNormal = 0, // src
kRenderTransColor, // c*a+dest*(1-a)
kRenderTransTexture, // src*a+dest*(1-a)
kRenderGlow, // src*a+dest -- No Z buffer checks -- Fixed size in screen space
kRenderTransAlpha, // src*srca+dest*(1-srca)
kRenderTransAdd, // src*a+dest
kRenderEnvironmental, // not drawn, used for environmental effects
kRenderTransAddFrameBlend, // use a fractional frame value to blend between animation frames
kRenderTransAlphaAdd, // src + dest*(1-a)
kRenderWorldGlow, // Same as kRenderGlow but not fixed size in screen space
kRenderNone, // Don't render.
kRenderModeCount, // must be last
};
enum RenderFx_t
{
kRenderFxNone = 0,
kRenderFxPulseSlow,
kRenderFxPulseFast,
kRenderFxPulseSlowWide,
kRenderFxPulseFastWide,
kRenderFxFadeSlow,
kRenderFxFadeFast,
kRenderFxSolidSlow,
kRenderFxSolidFast,
kRenderFxStrobeSlow,
kRenderFxStrobeFast,
kRenderFxStrobeFaster,
kRenderFxFlickerSlow,
kRenderFxFlickerFast,
kRenderFxNoDissipation,
kRenderFxDistort, // Distort/scale/translate flicker
kRenderFxHologram, // kRenderFxDistort + distance fade
kRenderFxExplode, // Scale up really big!
kRenderFxGlowShell, // Glowing Shell
kRenderFxClampMinScale, // Keep this sprite from getting very small (SPRITES only!)
kRenderFxEnvRain, // for environmental rendermode, make rain
kRenderFxEnvSnow, // " " " , make snow
kRenderFxSpotlight, // TEST CODE for experimental spotlight
kRenderFxRagdoll, // HACKHACK: TEST CODE for signalling death of a ragdoll character
kRenderFxPulseFastWider,
kRenderFxMax
};
enum Collision_Group_t
{
COLLISION_GROUP_NONE = 0,
COLLISION_GROUP_DEBRIS, // Collides with nothing but world and static stuff
COLLISION_GROUP_DEBRIS_TRIGGER, // Same as debris, but hits triggers
COLLISION_GROUP_INTERACTIVE_DEBRIS, // Collides with everything except other interactive debris or debris
COLLISION_GROUP_INTERACTIVE, // Collides with everything except interactive debris or debris
COLLISION_GROUP_PLAYER,
COLLISION_GROUP_BREAKABLE_GLASS,
COLLISION_GROUP_VEHICLE,
COLLISION_GROUP_PLAYER_MOVEMENT, // For HL2, same as Collision_Group_Player, for
// TF2, this filters out other players and CBaseObjects
COLLISION_GROUP_NPC, // Generic NPC group
COLLISION_GROUP_IN_VEHICLE, // for any entity inside a vehicle
COLLISION_GROUP_WEAPON, // for any weapons that need collision detection
COLLISION_GROUP_VEHICLE_CLIP, // vehicle clip brush to restrict vehicle movement
COLLISION_GROUP_PROJECTILE, // Projectiles!
COLLISION_GROUP_DOOR_BLOCKER, // Blocks entities not permitted to get near moving doors
COLLISION_GROUP_PASSABLE_DOOR, // Doors that the player shouldn't collide with
COLLISION_GROUP_DISSOLVING, // Things that are dissolving are in this group
COLLISION_GROUP_PUSHAWAY, // Nonsolid on client and server, pushaway in player code
COLLISION_GROUP_NPC_ACTOR, // Used so NPCs in scripts ignore the player.
COLLISION_GROUP_NPC_SCRIPTED, // USed for NPCs in scripts that should not collide with each other
LAST_SHARED_COLLISION_GROUP
};
#include "basetypes.h"
#define SOUND_NORMAL_CLIP_DIST 1000.0f
// How many networked area portals do we allow?
#define MAX_AREA_STATE_BYTES 32
#define MAX_AREA_PORTAL_STATE_BYTES 24
// user message max payload size (note, this value is used by the engine, so MODs cannot change it)
#define MAX_USER_MSG_DATA 255
#define MAX_ENTITY_MSG_DATA 255
#define SOURCE_MT
#ifdef SOURCE_MT
class CThreadMutex;
typedef CThreadMutex CSourceMutex;
#else
class CThreadNullMutex;
typedef CThreadNullMutex CSourceMutex;
#endif
#endif

98
public/coordsize.h Normal file
View File

@ -0,0 +1,98 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef COORDSIZE_H
#define COORDSIZE_H
#pragma once
#include "worldsize.h"
// OVERALL Coordinate Size Limits used in COMMON.C MSG_*BitCoord() Routines (and someday the HUD)
#define COORD_INTEGER_BITS 14
#define COORD_FRACTIONAL_BITS 5
#define COORD_DENOMINATOR (1<<(COORD_FRACTIONAL_BITS))
#define COORD_RESOLUTION (1.0/(COORD_DENOMINATOR))
// Special threshold for networking multiplayer origins
#define COORD_INTEGER_BITS_MP 11
#define COORD_FRACTIONAL_BITS_MP_LOWPRECISION 3
#define COORD_DENOMINATOR_LOWPRECISION (1<<(COORD_FRACTIONAL_BITS_MP_LOWPRECISION))
#define COORD_RESOLUTION_LOWPRECISION (1.0/(COORD_DENOMINATOR_LOWPRECISION))
#define NORMAL_FRACTIONAL_BITS 11
#define NORMAL_DENOMINATOR ( (1<<(NORMAL_FRACTIONAL_BITS)) - 1 )
#define NORMAL_RESOLUTION (1.0/(NORMAL_DENOMINATOR))
// this is limited by the network fractional bits used for coords
// because net coords will be only be accurate to 5 bits fractional
// Standard collision test epsilon
// 1/32nd inch collision epsilon
#define DIST_EPSILON (0.03125)
// Verify that coordsize.h and worldsize.h are consistently defined
#if (MAX_COORD_INTEGER != (1<<COORD_INTEGER_BITS) )
#error MAX_COORD_INTEGER does not match COORD_INTEGER_BITS
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////
// The following are Bit Packing Diagrams for client/server Coordinate BitField Messages
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// "Coordinates" = +/-16384.9375 (21 Bits Max)
//
// | IntegerFlagBit:1 | FractionFlagBit:1 | SignBit:1 | IntegerField:14 | FractionPart:4 | Total
// --------------------------------------------------------------------------------------------------
// 0 0 - - - 2
// 0 1 x - xxxx 7
// 1 0 x xxxxxxxxxxxxx - 17
// 1 1 x xxxxxxxxxxxxx xxxx 21
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// "Vec3Coordinate" = Up to 3 Coordinates (66 Bits Max)
//
// | NonZeroX:1 | NonZeroY:1 | NonZeroZ:1 | 0..3 "Coordinates" | BitField Total
// -------------------------------------------------------------------------------
// 0 0 0 - 3
// 0 0 1 7..21 Bits 10..24
// 0 1 0 7..21 Bits 10..24
// 1 0 0 7..21 Bits 10..24
// 0 1 1 14..42 Bits 17..45
// 1 1 0 14..42 Bits 17..45
// 1 0 1 14..42 Bits 17..45
// 1 1 1 21..63 Bits 24..66
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
// The following are Bit Packing Diagrams for client/server Normal BitField Messages
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// "Normals" = +/-1.0 (12 Bits Total)
//
// The only gotcha here is that normalization occurs so that
// 011111111111 = +1.0 and 1111111111111 = -1.0
//
// | SignBit:1 | FractionPart:11 | Total
// --------------------------------------------------------------------------------------------------
// 1 xxxxxxxxxxx 12
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// "Vec3Normal" = Up to 3 Coordinates (27 Bits Max)
//
// | NonZeroX:1 | NonZeroY:1 | 0..2 "Coordinates" | Z Sign Bit | BitField Total
// -------------------------------------------------------------------------------
// 0 0 - x 3
// 0 1 12 Bits x 14
// 1 0 12 Bits x 14
// 1 1 24 Bits x 27
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
#endif // COORDSIZE_H

44
public/crtmemdebug.cpp Normal file
View File

@ -0,0 +1,44 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#if !defined(_STATIC_LINKED) || defined(_SHARED_LIB)
#include "crtmemdebug.h"
#ifdef USECRTMEMDEBUG
#include <crtdbg.h>
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
void CheckHeap( void )
{
#ifdef USECRTMEMDEBUG
_CrtCheckMemory();
#endif
}
// undone: this needs to be somehow made to construct before everything else.
// see http://msdn.microsoft.com/library/periodic/period97/dembugs.htm for info
void InitCRTMemDebug( void )
{
#ifdef USECRTMEMDEBUG
_CrtSetDbgFlag(
// _CRTDBG_ALLOC_MEM_DF |
_CRTDBG_CHECK_ALWAYS_DF |
_CRTDBG_CHECK_CRT_DF |
_CRTDBG_DELAY_FREE_MEM_DF );
#endif
}
#endif // !_STATIC_LINKED || _SHARED_LIB

33
public/crtmemdebug.h Normal file
View File

@ -0,0 +1,33 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#ifndef CRTMEMDEBUG_H
#define CRTMEMDEBUG_H
#pragma once
#ifdef USECRTMEMDEBUG
#include <crtdbg.h>
#define MEMCHECK CheckHeap()
void CheckHeap( void );
#else
#define MEMCHECK
#endif
void InitCRTMemDebug( void );
#endif // CRTMEMDEBUG_H

View File

@ -0,0 +1,545 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef IDATACACHE_H
#define IDATACACHE_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
#include "appframework/IAppSystem.h"
class IDataCache;
//-----------------------------------------------------------------------------
//
// Shared Data Cache API
//
//-----------------------------------------------------------------------------
#define DATACACHE_INTERFACE_VERSION "VDataCache003"
//-----------------------------------------------------------------------------
// Support types and enums
//-----------------------------------------------------------------------------
//---------------------------------------------------------
// Unique (per section) identifier for a cache item defined by client
//---------------------------------------------------------
typedef uint32 DataCacheClientID_t;
//---------------------------------------------------------
// Cache-defined handle for a cache item
//---------------------------------------------------------
FORWARD_DECLARE_HANDLE( memhandle_t );
typedef memhandle_t DataCacheHandle_t;
#define DC_INVALID_HANDLE ((DataCacheHandle_t)0)
//---------------------------------------------------------
// Cache Limits
//---------------------------------------------------------
struct DataCacheLimits_t
{
DataCacheLimits_t( unsigned _nMaxBytes = (unsigned)-1, unsigned _nMaxItems = (unsigned)-1, unsigned _nMinBytes = 0, unsigned _nMinItems = 0 )
: nMaxBytes(_nMaxBytes),
nMaxItems(_nMaxItems),
nMinBytes(_nMinBytes),
nMinItems(_nMinItems)
{
}
// Maximum levels permitted
unsigned nMaxBytes;
unsigned nMaxItems;
// Minimum levels permitted
unsigned nMinBytes;
unsigned nMinItems;
};
//---------------------------------------------------------
// Cache status
//---------------------------------------------------------
struct DataCacheStatus_t
{
// Current state of the cache
unsigned nBytes;
unsigned nItems;
unsigned nBytesLocked;
unsigned nItemsLocked;
// Diagnostics
unsigned nFindRequests;
unsigned nFindHits;
};
//---------------------------------------------------------
// Cache options
//---------------------------------------------------------
enum DataCacheOptions_t
{
DC_TRACE_ACTIVITY = (1 << 0),
DC_FORCE_RELOCATE = (1 << 1),
DC_ALWAYS_MISS = (1 << 2),
DC_VALIDATE = (1 << 3),
};
//---------------------------------------------------------
// Cache report types
//---------------------------------------------------------
enum DataCacheReportType_t
{
DC_SUMMARY_REPORT,
DC_DETAIL_REPORT,
DC_DETAIL_REPORT_LRU,
};
//---------------------------------------------------------
// Notifications to section clients on cache events
//---------------------------------------------------------
enum DataCacheNotificationType_t
{
// Used internally to prohibit notifications
DC_NONE,
// Item is falling off the LRU and should be deleted, return false to block
DC_AGE_DISCARD,
// Item is being explicitly flushed and should be deleted, return false to block
DC_FLUSH_DISCARD,
// Item is being explicitly removed and should be deleted. Failure is not an option
DC_REMOVED,
// Cache is requesting item be relocated for debugging purposes
DC_RELOCATE,
// Item info should be output to console, return false to accept default handling
DC_PRINT_INF0,
};
//-------------------------------------
struct DataCacheNotification_t
{
DataCacheNotificationType_t type;
const char * pszSectionName;
DataCacheClientID_t clientId;
const void * pItemData;
unsigned nItemSize;
};
//---------------------------------------------------------
const int DC_MAX_CLIENT_NAME = 15;
const int DC_MAX_ITEM_NAME = 511;
//---------------------------------------------------------
// Result codes
//---------------------------------------------------------
enum DataCacheRemoveResult_t
{
DC_OK,
DC_NOT_FOUND,
DC_LOCKED,
};
//---------------------------------------------------------
// Add flags
//---------------------------------------------------------
enum DataCacheAddFlags_t
{
DCAF_LOCK = ( 1 << 0 ),
DCAF_DEFAULT = 0,
};
//-----------------------------------------------------------------------------
// IDataCacheSection
//
// Purpose: Implements a sub-section of the global cache. Subsections are
// areas of the cache with thier own memory constraints and common
// management.
//-----------------------------------------------------------------------------
abstract_class IDataCacheSection
{
public:
//--------------------------------------------------------
virtual IDataCache *GetSharedCache() = 0;
virtual const char *GetName() = 0;
//--------------------------------------------------------
// Purpose: Controls cache size & options
//--------------------------------------------------------
virtual void SetLimits( const DataCacheLimits_t &limits ) = 0;
virtual void SetOptions( unsigned options ) = 0;
//--------------------------------------------------------
// Purpose: Get the current state of the section
//--------------------------------------------------------
virtual void GetStatus( DataCacheStatus_t *pStatus, DataCacheLimits_t *pLimits = NULL ) = 0;
//--------------------------------------------------------
// Purpose: Add an item to the cache. Purges old items if over budget, returns false if item was already in cache.
//--------------------------------------------------------
virtual void EnsureCapacity( unsigned nBytes, unsigned nItems = 1 ) = 0;
//--------------------------------------------------------
// Purpose: Add an item to the cache. Purges old items if over budget, returns false if item was already in cache.
//--------------------------------------------------------
virtual bool Add( DataCacheClientID_t clientId, const void *pItemData, unsigned size, DataCacheHandle_t *pHandle ) = 0;
//--------------------------------------------------------
// Purpose: Finds an item in the cache, returns NULL if item is not in cache. Not a cheap operation if section not configured for fast find.
//--------------------------------------------------------
virtual DataCacheHandle_t Find( DataCacheClientID_t clientId ) = 0;
//--------------------------------------------------------
// Purpose: Get an item out of the cache and remove it. No callbacks are executed unless explicity specified.
//--------------------------------------------------------
virtual DataCacheRemoveResult_t Remove( DataCacheHandle_t handle, const void **ppItemData, unsigned *pItemSize = NULL, bool bNotify = false ) = 0;
DataCacheRemoveResult_t Remove( DataCacheHandle_t handle, bool bNotify = false ) { return Remove( handle, NULL, NULL, bNotify ); }
//--------------------------------------------------------
// Purpose: Returns if the data is currently in memory, but does *not* change its location in the LRU
//--------------------------------------------------------
virtual bool IsPresent( DataCacheHandle_t handle ) = 0;
//--------------------------------------------------------
// Purpose: Lock an item in the cache, returns NULL if item is not in the cache.
//--------------------------------------------------------
virtual void *Lock( DataCacheHandle_t handle ) = 0;
//--------------------------------------------------------
// Purpose: Unlock a previous lock.
//--------------------------------------------------------
virtual int Unlock( DataCacheHandle_t handle ) = 0;
//--------------------------------------------------------
// Purpose: Get an item without locking it, returns NULL if item is not in the cache. Use with care!
//--------------------------------------------------------
virtual void *Get( DataCacheHandle_t handle, bool bFrameLock = false ) = 0;
virtual void *GetNoTouch( DataCacheHandle_t handle, bool bFrameLock = false ) = 0;
//--------------------------------------------------------
// Purpose: "Frame locking" (not game frame). A crude way to manage locks over relatively
// short periods. Does not affect normal locks/unlocks
//--------------------------------------------------------
virtual int BeginFrameLocking() = 0;
virtual bool IsFrameLocking() = 0;
virtual void *FrameLock( DataCacheHandle_t handle ) = 0;
virtual int EndFrameLocking() = 0;
virtual int *GetFrameUnlockCounterPtr() = 0;
//--------------------------------------------------------
// Purpose: Lock management, not for the feint of heart
//--------------------------------------------------------
virtual int GetLockCount( DataCacheHandle_t handle ) = 0;
virtual int BreakLock( DataCacheHandle_t handle ) = 0;
//--------------------------------------------------------
// Purpose: Explicitly mark an item as "recently used"
//--------------------------------------------------------
virtual bool Touch( DataCacheHandle_t handle ) = 0;
//--------------------------------------------------------
// Purpose: Explicitly mark an item as "least recently used".
//--------------------------------------------------------
virtual bool Age( DataCacheHandle_t handle ) = 0;
//--------------------------------------------------------
// Purpose: Empty the cache. Returns bytes released, will remove locked items if force specified
//--------------------------------------------------------
virtual unsigned Flush( bool bUnlockedOnly = true, bool bNotify = true ) = 0;
//--------------------------------------------------------
// Purpose: Dump the oldest items to free the specified amount of memory. Returns amount actually freed
//--------------------------------------------------------
virtual unsigned Purge( unsigned nBytes ) = 0;
//--------------------------------------------------------
// Purpose: Output the state of the section
//--------------------------------------------------------
virtual void OutputReport( DataCacheReportType_t reportType = DC_SUMMARY_REPORT ) = 0;
//--------------------------------------------------------
// Purpose: Updates the size used by a specific item (locks the item, kicks
// other items out to make room as necessary, unlocks the item).
//--------------------------------------------------------
virtual void UpdateSize( DataCacheHandle_t handle, unsigned int nNewSize ) = 0;
//--------------------------------------------------------
// Purpose: Access to the mutex. More explicit control during get-then-lock sequences
// to ensure object stays valid during "then"
//--------------------------------------------------------
virtual void LockMutex() = 0;
virtual void UnlockMutex() = 0;
//--------------------------------------------------------
// Purpose: Add an item to the cache. Purges old items if over budget, returns false if item was already in cache.
//--------------------------------------------------------
virtual bool AddEx( DataCacheClientID_t clientId, const void *pItemData, unsigned size, unsigned flags, DataCacheHandle_t *pHandle ) = 0;
};
//-----------------------------------------------------------------------------
// IDataCacheClient
//
// Purpose: Connection between the cache and the owner of a cache section
//
//-----------------------------------------------------------------------------
abstract_class IDataCacheClient
{
public:
//--------------------------------------------------------
//
//--------------------------------------------------------
virtual bool HandleCacheNotification( const DataCacheNotification_t &notification ) = 0;
//--------------------------------------------------------
//
//--------------------------------------------------------
virtual bool GetItemName( DataCacheClientID_t clientId, const void *pItem, char *pDest, unsigned nMaxLen ) = 0;
};
//-------------------------------------
class CDefaultDataCacheClient : public IDataCacheClient
{
public:
virtual bool HandleCacheNotification( const DataCacheNotification_t &notification )
{
switch ( notification.type )
{
case DC_AGE_DISCARD:
case DC_FLUSH_DISCARD:
case DC_REMOVED:
default:
Assert ( 0 );
return false;
}
return false;
}
virtual bool GetItemName( DataCacheClientID_t clientId, const void *pItem, char *pDest, unsigned nMaxLen )
{
return false;
}
};
//-----------------------------------------------------------------------------
// IDataCache
//
// Purpose: The global shared cache. Manages sections and overall budgets.
//
//-----------------------------------------------------------------------------
abstract_class IDataCache : public IAppSystem
{
public:
//--------------------------------------------------------
// Purpose: Controls cache size.
//--------------------------------------------------------
virtual void SetSize( int nMaxBytes ) = 0;
virtual void SetOptions( unsigned options ) = 0;
virtual void SetSectionLimits( const char *pszSectionName, const DataCacheLimits_t &limits ) = 0;
//--------------------------------------------------------
// Purpose: Get the current state of the cache
//--------------------------------------------------------
virtual void GetStatus( DataCacheStatus_t *pStatus, DataCacheLimits_t *pLimits = NULL ) = 0;
//--------------------------------------------------------
// Purpose: Add a section to the cache
//--------------------------------------------------------
virtual IDataCacheSection *AddSection( IDataCacheClient *pClient, const char *pszSectionName, const DataCacheLimits_t &limits = DataCacheLimits_t(), bool bSupportFastFind = false ) = 0;
//--------------------------------------------------------
// Purpose: Remove a section from the cache
//--------------------------------------------------------
virtual void RemoveSection( const char *pszClientName, bool bCallFlush = true ) = 0;
void RemoveSection( IDataCacheSection *pSection, bool bCallFlush = true ) { if ( pSection) RemoveSection( pSection->GetName() ); }
//--------------------------------------------------------
// Purpose: Find a section of the cache
//--------------------------------------------------------
virtual IDataCacheSection *FindSection( const char *pszClientName ) = 0;
//--------------------------------------------------------
// Purpose: Dump the oldest items to free the specified amount of memory. Returns amount actually freed
//--------------------------------------------------------
virtual unsigned Purge( unsigned nBytes ) = 0;
//--------------------------------------------------------
// Purpose: Empty the cache. Returns bytes released, will remove locked items if force specified
//--------------------------------------------------------
virtual unsigned Flush( bool bUnlockedOnly = true, bool bNotify = true ) = 0;
//--------------------------------------------------------
// Purpose: Output the state of the cache
//--------------------------------------------------------
virtual void OutputReport( DataCacheReportType_t reportType = DC_SUMMARY_REPORT, const char *pszSection = NULL ) = 0;
};
//-----------------------------------------------------------------------------
// Helper class to support usage pattern similar to CDataManager
//-----------------------------------------------------------------------------
template< class STORAGE_TYPE, class CREATE_PARAMS, class LOCK_TYPE = STORAGE_TYPE * >
class CManagedDataCacheClient : public CDefaultDataCacheClient
{
public:
typedef CManagedDataCacheClient<STORAGE_TYPE, CREATE_PARAMS, LOCK_TYPE> CCacheClientBaseClass;
CManagedDataCacheClient()
: m_pCache( NULL )
{
}
void Init( IDataCache *pSharedCache, const char *pszSectionName, const DataCacheLimits_t &limits = DataCacheLimits_t(), bool bSupportFastFind = false )
{
if ( !m_pCache )
{
m_pCache = pSharedCache->AddSection( this, pszSectionName, limits, bSupportFastFind );
}
}
void Shutdown()
{
if ( m_pCache )
{
m_pCache->GetSharedCache()->RemoveSection( m_pCache );
m_pCache = NULL;
}
}
LOCK_TYPE CacheGet( DataCacheHandle_t handle, bool bFrameLock = true )
{
return (LOCK_TYPE)(((STORAGE_TYPE *)m_pCache->Get( handle, bFrameLock ))->GetData());
}
LOCK_TYPE CacheGetNoTouch( DataCacheHandle_t handle )
{
return (LOCK_TYPE)(((STORAGE_TYPE *)m_pCache->GetNoTouch( handle ))->GetData());
}
LOCK_TYPE CacheLock( DataCacheHandle_t handle )
{
return (LOCK_TYPE)(((STORAGE_TYPE *)m_pCache->Lock( handle ))->GetData());
}
int CacheUnlock( DataCacheHandle_t handle )
{
return m_pCache->Unlock( handle );
}
void CacheTouch( DataCacheHandle_t handle )
{
m_pCache->Touch( handle );
}
void CacheRemove( DataCacheHandle_t handle, bool bNotify = true )
{
m_pCache->Remove( handle, bNotify );
}
void CacheFlush()
{
m_pCache->Flush();
}
DataCacheHandle_t CacheCreate( const CREATE_PARAMS &createParams, unsigned flags = DCAF_DEFAULT )
{
m_pCache->EnsureCapacity(STORAGE_TYPE::EstimatedSize(createParams));
STORAGE_TYPE *pStore = STORAGE_TYPE::CreateResource( createParams );
DataCacheHandle_t handle;
m_pCache->AddEx( (DataCacheClientID_t)pStore, pStore, pStore->Size(), flags, &handle);
return handle;
}
void CacheLockMutex()
{
m_pCache->LockMutex();
}
void CacheUnlockMutex()
{
m_pCache->UnlockMutex();
}
bool HandleCacheNotification( const DataCacheNotification_t &notification )
{
switch ( notification.type )
{
case DC_AGE_DISCARD:
case DC_FLUSH_DISCARD:
case DC_REMOVED:
{
STORAGE_TYPE *p = (STORAGE_TYPE *)notification.clientId;
p->DestroyResource();
}
return true;
default:
return CDefaultDataCacheClient::HandleCacheNotification( notification );
}
}
protected:
~CManagedDataCacheClient()
{
Shutdown();
}
IDataCacheSection *GetCacheSection()
{
return m_pCache;
}
private:
IDataCacheSection *m_pCache;
};
//-----------------------------------------------------------------------------
#endif // IDataCache

View File

@ -0,0 +1,297 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// model loading and caching
//
//=============================================================================
#ifndef IMDLCACHE_H
#define IMDLCACHE_H
#ifdef _WIN32
#pragma once
#endif
#include "appframework/IAppSystem.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct studiohdr_t;
struct studiohwdata_t;
struct vcollide_t;
struct virtualmodel_t;
struct vertexFileHeader_t;
namespace OptimizedModel
{
struct FileHeader_t;
}
//-----------------------------------------------------------------------------
// Reference to a loaded studiomdl
//-----------------------------------------------------------------------------
typedef unsigned short MDLHandle_t;
enum
{
MDLHANDLE_INVALID = (MDLHandle_t)~0
};
//-----------------------------------------------------------------------------
// Cache data types
//-----------------------------------------------------------------------------
enum MDLCacheDataType_t
{
// Callbacks to get called when data is loaded or unloaded for these:
MDLCACHE_STUDIOHDR = 0,
MDLCACHE_STUDIOHWDATA,
MDLCACHE_VCOLLIDE,
// Callbacks NOT called when data is loaded or unloaded for these:
MDLCACHE_ANIMBLOCK,
MDLCACHE_VIRTUALMODEL,
MDLCACHE_VERTEXES,
MDLCACHE_DECODEDANIMBLOCK,
};
abstract_class IMDLCacheNotify
{
public:
// Called right after the data is loaded
virtual void OnDataLoaded( MDLCacheDataType_t type, MDLHandle_t handle ) = 0;
// Called right before the data is unloaded
virtual void OnDataUnloaded( MDLCacheDataType_t type, MDLHandle_t handle ) = 0;
};
//-----------------------------------------------------------------------------
// Flags for flushing
//-----------------------------------------------------------------------------
enum MDLCacheFlush_t
{
MDLCACHE_FLUSH_STUDIOHDR = 0x01,
MDLCACHE_FLUSH_STUDIOHWDATA = 0x02,
MDLCACHE_FLUSH_VCOLLIDE = 0x04,
MDLCACHE_FLUSH_ANIMBLOCK = 0x08,
MDLCACHE_FLUSH_VIRTUALMODEL = 0x10,
MDLCACHE_FLUSH_AUTOPLAY = 0x20,
MDLCACHE_FLUSH_VERTEXES = 0x40,
MDLCACHE_FLUSH_IGNORELOCK = 0x80000000,
MDLCACHE_FLUSH_ALL = 0xFFFFFFFF
};
/*
#define MDLCACHE_INTERFACE_VERSION_4 "MDLCache004"
namespace MDLCacheV4
{
abstract_class IMDLCache : public IAppSystem
{
public:
// Used to install callbacks for when data is loaded + unloaded
virtual void SetCacheNotify( IMDLCacheNotify *pNotify ) = 0;
// NOTE: This assumes the "GAME" path if you don't use
// the UNC method of specifying files. This will also increment
// the reference count of the MDL
virtual MDLHandle_t FindMDL( const char *pMDLRelativePath ) = 0;
// Reference counting
virtual int AddRef( MDLHandle_t handle ) = 0;
virtual int Release( MDLHandle_t handle ) = 0;
// Gets at the various data associated with a MDL
virtual studiohdr_t *GetStudioHdr( MDLHandle_t handle ) = 0;
virtual studiohwdata_t *GetHardwareData( MDLHandle_t handle ) = 0;
virtual vcollide_t *GetVCollide( MDLHandle_t handle ) = 0;
virtual unsigned char *GetAnimBlock( MDLHandle_t handle, int nBlock ) = 0;
virtual virtualmodel_t *GetVirtualModel( MDLHandle_t handle ) = 0;
virtual int GetAutoplayList( MDLHandle_t handle, unsigned short **pOut ) = 0;
virtual vertexFileHeader_t *GetVertexData( MDLHandle_t handle ) = 0;
// Brings all data associated with an MDL into memory
virtual void TouchAllData( MDLHandle_t handle ) = 0;
// Gets/sets user data associated with the MDL
virtual void SetUserData( MDLHandle_t handle, void* pData ) = 0;
virtual void *GetUserData( MDLHandle_t handle ) = 0;
// Is this MDL using the error model?
virtual bool IsErrorModel( MDLHandle_t handle ) = 0;
// Flushes the cache, force a full discard
virtual void Flush( int nFlushFlags = MDLCACHE_FLUSH_ALL ) = 0;
// Flushes a particular model out of memory
virtual void Flush( MDLHandle_t handle, int nFlushFlags = MDLCACHE_FLUSH_ALL ) = 0;
// Returns the name of the model (its relative path)
virtual const char *GetModelName( MDLHandle_t handle ) = 0;
// faster access when you already have the studiohdr
virtual virtualmodel_t *GetVirtualModelFast( const studiohdr_t *pStudioHdr, MDLHandle_t handle ) = 0;
// all cache entries that subsequently allocated or successfully checked
// are considered "locked" and will not be freed when additional memory is needed
virtual void BeginLock() = 0;
// reset all protected blocks to normal
virtual void EndLock() = 0;
// returns a pointer to a counter that is incremented every time the cache has been out of the locked state (EVIL)
virtual int *GetFrameUnlockCounterPtr() = 0;
// Finish all pending async operations
virtual void FinishPendingLoads() = 0;
};
}
*/
//-----------------------------------------------------------------------------
// The main MDL cacher
//-----------------------------------------------------------------------------
#define MDLCACHE_INTERFACE_VERSION "MDLCache004"
abstract_class IMDLCache : public IAppSystem
{
public:
// Used to install callbacks for when data is loaded + unloaded
// Returns the prior notify
virtual void SetCacheNotify( IMDLCacheNotify *pNotify ) = 0;
// NOTE: This assumes the "GAME" path if you don't use
// the UNC method of specifying files. This will also increment
// the reference count of the MDL
virtual MDLHandle_t FindMDL( const char *pMDLRelativePath ) = 0;
// Reference counting
virtual int AddRef( MDLHandle_t handle ) = 0;
virtual int Release( MDLHandle_t handle ) = 0;
virtual int GetRef( MDLHandle_t handle ) = 0;
// Gets at the various data associated with a MDL
virtual studiohdr_t *GetStudioHdr( MDLHandle_t handle ) = 0;
virtual studiohwdata_t *GetHardwareData( MDLHandle_t handle ) = 0;
virtual vcollide_t *GetVCollide( MDLHandle_t handle ) = 0;
virtual unsigned char *GetAnimBlock( MDLHandle_t handle, int nBlock ) = 0;
virtual virtualmodel_t *GetVirtualModel( MDLHandle_t handle ) = 0;
virtual int GetAutoplayList( MDLHandle_t handle, unsigned short **pOut ) = 0;
virtual vertexFileHeader_t *GetVertexData( MDLHandle_t handle ) = 0;
// Brings all data associated with an MDL into memory
virtual void TouchAllData( MDLHandle_t handle ) = 0;
// Gets/sets user data associated with the MDL
virtual void SetUserData( MDLHandle_t handle, void* pData ) = 0;
virtual void *GetUserData( MDLHandle_t handle ) = 0;
// Is this MDL using the error model?
virtual bool IsErrorModel( MDLHandle_t handle ) = 0;
// Flushes the cache, force a full discard
virtual void Flush( MDLCacheFlush_t nFlushFlags = MDLCACHE_FLUSH_ALL ) = 0;
// Flushes a particular model out of memory
virtual void Flush( MDLHandle_t handle, int nFlushFlags = MDLCACHE_FLUSH_ALL ) = 0;
// Returns the name of the model (its relative path)
virtual const char *GetModelName( MDLHandle_t handle ) = 0;
// faster access when you already have the studiohdr
virtual virtualmodel_t *GetVirtualModelFast( const studiohdr_t *pStudioHdr, MDLHandle_t handle ) = 0;
// all cache entries that subsequently allocated or successfully checked
// are considered "locked" and will not be freed when additional memory is needed
virtual void BeginLock() = 0;
// reset all protected blocks to normal
virtual void EndLock() = 0;
// returns a pointer to a counter that is incremented every time the cache has been out of the locked state (EVIL)
virtual int *GetFrameUnlockCounterPtrOLD() = 0;
// Finish all pending async operations
virtual void FinishPendingLoads() = 0;
virtual vcollide_t *GetVCollideEx( MDLHandle_t handle, bool synchronousLoad = true ) = 0;
virtual bool GetVCollideSize( MDLHandle_t handle, int *pVCollideSize ) = 0;
virtual bool GetAsyncLoad( MDLCacheDataType_t type ) = 0;
virtual bool SetAsyncLoad( MDLCacheDataType_t type, bool bAsync ) = 0;
virtual void BeginMapLoad() = 0;
virtual void EndMapLoad() = 0;
virtual void MarkAsLoaded( MDLHandle_t handle ) = 0;
virtual void InitPreloadData( bool rebuild ) = 0;
virtual void ShutdownPreloadData() = 0;
virtual bool IsDataLoaded( MDLHandle_t handle, MDLCacheDataType_t type ) = 0;
virtual int *GetFrameUnlockCounterPtr( MDLCacheDataType_t type ) = 0;
virtual studiohdr_t *LockStudioHdr( MDLHandle_t handle ) = 0;
virtual void UnlockStudioHdr( MDLHandle_t handle ) = 0;
virtual bool PreloadModel( MDLHandle_t handle ) = 0;
// Hammer uses this. If a model has an error loading in GetStudioHdr, then it is flagged
// as an error model and any further attempts to load it will just get the error model.
// That is, until you call this function. Then it will load the correct model.
virtual void ResetErrorModelStatus( MDLHandle_t handle ) = 0;
virtual void MarkFrame() = 0;
};
//-----------------------------------------------------------------------------
// Critical section helper code
//-----------------------------------------------------------------------------
class CMDLCacheCriticalSection
{
public:
CMDLCacheCriticalSection( IMDLCache *pCache ) : m_pCache( pCache )
{
m_pCache->BeginLock();
}
~CMDLCacheCriticalSection()
{
m_pCache->EndLock();
}
private:
IMDLCache *m_pCache;
};
#define MDCACHE_FINE_GRAINED 1
#if defined(MDCACHE_FINE_GRAINED)
#define MDLCACHE_CRITICAL_SECTION_( pCache ) CMDLCacheCriticalSection cacheCriticalSection(pCache)
#define MDLCACHE_COARSE_LOCK_( pCache ) ((void)(0))
#elif defined(MDLCACHE_LEVEL_LOCKED)
#define MDLCACHE_CRITICAL_SECTION_( pCache ) ((void)(0))
#define MDLCACHE_COARSE_LOCK_( pCache ) ((void)(0))
#else
#define MDLCACHE_CRITICAL_SECTION_( pCache ) ((void)(0))
#define MDLCACHE_COARSE_LOCK_( pCache ) CMDLCacheCriticalSection cacheCriticalSection(pCache)
#endif
#define MDLCACHE_CRITICAL_SECTION() MDLCACHE_CRITICAL_SECTION_(mdlcache)
#define MDLCACHE_COARSE_LOCK() MDLCACHE_COARSE_LOCK_(mdlcache)
#endif // IMDLCACHE_H

455
public/datamap.h Normal file
View File

@ -0,0 +1,455 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef DATAMAP_H
#define DATAMAP_H
#ifdef _WIN32
#pragma once
#endif
#ifndef VECTOR_H
#include "mathlib/vector.h"
#endif
#include "tier1/utlvector.h"
#include "tier0/memdbgon.h"
// SINGLE_INHERITANCE restricts the size of CBaseEntity pointers-to-member-functions to 4 bytes
class SINGLE_INHERITANCE CBaseEntity;
struct inputdata_t;
#define INVALID_TIME (FLT_MAX * -1.0) // Special value not rebased on save/load
typedef enum _fieldtypes
{
FIELD_VOID = 0, // No type or value
FIELD_FLOAT, // Any floating point value
FIELD_STRING, // A string ID (return from ALLOC_STRING)
FIELD_VECTOR, // Any vector, QAngle, or AngularImpulse
FIELD_QUATERNION, // A quaternion
FIELD_INTEGER, // Any integer or enum
FIELD_BOOLEAN, // boolean, implemented as an int, I may use this as a hint for compression
FIELD_SHORT, // 2 byte integer
FIELD_CHARACTER, // a byte
FIELD_COLOR32, // 8-bit per channel r,g,b,a (32bit color)
FIELD_EMBEDDED, // an embedded object with a datadesc, recursively traverse and embedded class/structure based on an additional typedescription
FIELD_CUSTOM, // special type that contains function pointers to it's read/write/parse functions
FIELD_CLASSPTR, // CBaseEntity *
FIELD_EHANDLE, // Entity handle
FIELD_EDICT, // edict_t *
FIELD_POSITION_VECTOR, // A world coordinate (these are fixed up across level transitions automagically)
FIELD_TIME, // a floating point time (these are fixed up automatically too!)
FIELD_TICK, // an integer tick count( fixed up similarly to time)
FIELD_MODELNAME, // Engine string that is a model name (needs precache)
FIELD_SOUNDNAME, // Engine string that is a sound name (needs precache)
FIELD_INPUT, // a list of inputed data fields (all derived from CMultiInputVar)
FIELD_FUNCTION, // A class function pointer (Think, Use, etc)
FIELD_VMATRIX, // a vmatrix (output coords are NOT worldspace)
// NOTE: Use float arrays for local transformations that don't need to be fixed up.
FIELD_VMATRIX_WORLDSPACE,// A VMatrix that maps some local space to world space (translation is fixed up on level transitions)
FIELD_MATRIX3X4_WORLDSPACE, // matrix3x4_t that maps some local space to world space (translation is fixed up on level transitions)
FIELD_INTERVAL, // a start and range floating point interval ( e.g., 3.2->3.6 == 3.2 and 0.4 )
FIELD_MODELINDEX, // a model index
FIELD_MATERIALINDEX, // a material index (using the material precache string table)
FIELD_VECTOR2D, // 2 floats
FIELD_TYPECOUNT, // MUST BE LAST
} fieldtype_t;
//-----------------------------------------------------------------------------
// Field sizes...
//-----------------------------------------------------------------------------
template <int FIELD_TYPE>
class CDatamapFieldSizeDeducer
{
public:
enum
{
SIZE = 0
};
static int FieldSize( )
{
return 0;
}
};
#define DECLARE_FIELD_SIZE( _fieldType, _fieldSize ) \
template< > class CDatamapFieldSizeDeducer<_fieldType> { public: enum { SIZE = _fieldSize }; static int FieldSize() { return _fieldSize; } };
#define FIELD_SIZE( _fieldType ) CDatamapFieldSizeDeducer<_fieldType>::SIZE
#define FIELD_BITS( _fieldType ) (FIELD_SIZE( _fieldType ) * 8)
DECLARE_FIELD_SIZE( FIELD_FLOAT, sizeof(float) )
DECLARE_FIELD_SIZE( FIELD_STRING, sizeof(int) )
DECLARE_FIELD_SIZE( FIELD_VECTOR, 3 * sizeof(float) )
DECLARE_FIELD_SIZE( FIELD_VECTOR2D, 2 * sizeof(float) )
DECLARE_FIELD_SIZE( FIELD_QUATERNION, 4 * sizeof(float))
DECLARE_FIELD_SIZE( FIELD_INTEGER, sizeof(int))
DECLARE_FIELD_SIZE( FIELD_BOOLEAN, sizeof(char))
DECLARE_FIELD_SIZE( FIELD_SHORT, sizeof(short))
DECLARE_FIELD_SIZE( FIELD_CHARACTER, sizeof(char))
DECLARE_FIELD_SIZE( FIELD_COLOR32, sizeof(int))
DECLARE_FIELD_SIZE( FIELD_CLASSPTR, sizeof(int))
DECLARE_FIELD_SIZE( FIELD_EHANDLE, sizeof(int))
DECLARE_FIELD_SIZE( FIELD_EDICT, sizeof(int))
DECLARE_FIELD_SIZE( FIELD_POSITION_VECTOR, 3 * sizeof(float))
DECLARE_FIELD_SIZE( FIELD_TIME, sizeof(float))
DECLARE_FIELD_SIZE( FIELD_TICK, sizeof(int))
DECLARE_FIELD_SIZE( FIELD_MODELNAME, sizeof(int))
DECLARE_FIELD_SIZE( FIELD_SOUNDNAME, sizeof(int))
DECLARE_FIELD_SIZE( FIELD_INPUT, sizeof(int))
#ifdef POSIX
// pointer to members under gnuc are 8bytes if you have a virtual func
DECLARE_FIELD_SIZE( FIELD_FUNCTION, sizeof(uint64))
#else
DECLARE_FIELD_SIZE( FIELD_FUNCTION, sizeof(int *))
#endif
DECLARE_FIELD_SIZE( FIELD_VMATRIX, 16 * sizeof(float))
DECLARE_FIELD_SIZE( FIELD_VMATRIX_WORLDSPACE, 16 * sizeof(float))
DECLARE_FIELD_SIZE( FIELD_MATRIX3X4_WORLDSPACE, 12 * sizeof(float))
DECLARE_FIELD_SIZE( FIELD_INTERVAL, 2 * sizeof( float) ) // NOTE: Must match interval.h definition
DECLARE_FIELD_SIZE( FIELD_MODELINDEX, sizeof(int) )
DECLARE_FIELD_SIZE( FIELD_MATERIALINDEX, sizeof(int) )
#define ARRAYSIZE2D(p) (sizeof(p)/sizeof(p[0][0]))
#define SIZE_OF_ARRAY(p) _ARRAYSIZE(p)
#define _FIELD(name,fieldtype,count,flags,mapname,tolerance) { fieldtype, #name, { offsetof(classNameTypedef, name), 0 }, count, flags, mapname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, tolerance }
#define DEFINE_FIELD_NULL { FIELD_VOID,0, {0,0},0,0,0,0,0,0}
#define DEFINE_FIELD(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_SAVE, NULL, 0 )
#define DEFINE_KEYFIELD(name,fieldtype, mapname) _FIELD(name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 )
#define DEFINE_KEYFIELD_NOT_SAVED(name,fieldtype, mapname)_FIELD(name, fieldtype, 1, FTYPEDESC_KEY, mapname, 0 )
#define DEFINE_AUTO_ARRAY(name,fieldtype) _FIELD(name, fieldtype, SIZE_OF_ARRAY(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, 0 )
#define DEFINE_AUTO_ARRAY_KEYFIELD(name,fieldtype,mapname) _FIELD(name, fieldtype, SIZE_OF_ARRAY(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, mapname, 0 )
#define DEFINE_ARRAY(name,fieldtype, count) _FIELD(name, fieldtype, count, FTYPEDESC_SAVE, NULL, 0 )
#define DEFINE_ENTITY_FIELD(name,fieldtype) _FIELD(edict_t, name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE, #name, 0 )
#define DEFINE_ENTITY_GLOBAL_FIELD(name,fieldtype) _FIELD(edict_t, name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE | FTYPEDESC_GLOBAL, #name, 0 )
#define DEFINE_GLOBAL_FIELD(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_GLOBAL | FTYPEDESC_SAVE, NULL, 0 )
#define DEFINE_GLOBAL_KEYFIELD(name,fieldtype, mapname) _FIELD(name, fieldtype, 1, FTYPEDESC_GLOBAL | FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 )
#define DEFINE_CUSTOM_FIELD(name,datafuncs) { FIELD_CUSTOM, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, datafuncs, NULL }
#define DEFINE_CUSTOM_KEYFIELD(name,datafuncs,mapname) { FIELD_CUSTOM, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_KEY, mapname, datafuncs, NULL }
#define DEFINE_AUTO_ARRAY2D(name,fieldtype) _FIELD(name, fieldtype, ARRAYSIZE2D(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, 0 )
// Used by byteswap datadescs
#define DEFINE_BITFIELD(name,fieldtype,bitcount) DEFINE_ARRAY(name,fieldtype,((bitcount+FIELD_BITS(fieldtype)-1)&~(FIELD_BITS(fieldtype)-1)) / FIELD_BITS(fieldtype) )
#define DEFINE_INDEX(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_INDEX, NULL, 0 )
#define DEFINE_EMBEDDED( name ) \
{ FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name.m_DataMap), sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f }
#define DEFINE_EMBEDDED_OVERRIDE( name, overridetype ) \
{ FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &((overridetype *)0)->m_DataMap, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f }
#define DEFINE_EMBEDDEDBYREF( name ) \
{ FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( *(((classNameTypedef *)0)->name) ), NULL, 0, 0.0f }
#define DEFINE_EMBEDDED_ARRAY( name, count ) \
{ FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, count, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f }
#define DEFINE_EMBEDDED_AUTO_ARRAY( name ) \
{ FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, SIZE_OF_ARRAY( ((classNameTypedef *)0)->name ), FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f }
#ifndef NO_ENTITY_PREDICTION
#define DEFINE_PRED_TYPEDESCRIPTION( name, fieldtype ) \
{ FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &fieldtype::m_PredMap }
#define DEFINE_PRED_TYPEDESCRIPTION_PTR( name, fieldtype ) \
{ FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &fieldtype::m_PredMap }
#else
#define DEFINE_PRED_TYPEDESCRIPTION( name, fieldtype ) DEFINE_FIELD_NULL
#define DEFINE_PRED_TYPEDESCRIPTION_PTR( name, fieldtype ) DEFINE_FIELD_NULL
#endif
// Extensions to datamap.h macros for predicted entities only
#define DEFINE_PRED_FIELD(name,fieldtype, flags) _FIELD(name, fieldtype, 1, flags, NULL, 0.0f )
#define DEFINE_PRED_ARRAY(name,fieldtype, count,flags) _FIELD(name, fieldtype, count, flags, NULL, 0.0f )
#define DEFINE_FIELD_NAME(localname,netname,fieldtype) _FIELD(localname, fieldtype, 1, 0, #netname, 0.0f )
// Predictable macros, which include a tolerance for floating point values...
#define DEFINE_PRED_FIELD_TOL(name,fieldtype, flags,tolerance) _FIELD(name, fieldtype, 1, flags, NULL, tolerance )
#define DEFINE_PRED_ARRAY_TOL(name,fieldtype, count,flags,tolerance) _FIELD(name, fieldtype, count, flags, NULL, tolerance)
#define DEFINE_FIELD_NAME_TOL(localname,netname,fieldtolerance) _FIELD(localname, fieldtype, 1, 0, #netname, tolerance )
//#define DEFINE_DATA( name, fieldextname, flags ) _FIELD(name, fieldtype, 1, flags, extname )
// INPUTS
#define DEFINE_INPUT( name, fieldtype, inputname ) { fieldtype, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_INPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, inputname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ) }
#define DEFINE_INPUTFUNC( fieldtype, inputname, inputfunc ) { fieldtype, #inputfunc, { NULL, NULL }, 1, FTYPEDESC_INPUT, inputname, NULL, static_cast <inputfunc_t> (&classNameTypedef::inputfunc) }
// OUTPUTS
// the variable 'name' MUST BE derived from CBaseOutput
// we know the output type from the variable itself, so it doesn't need to be specified here
class ISaveRestoreOps;
extern ISaveRestoreOps *eventFuncs;
#define DEFINE_OUTPUT( name, outputname ) { FIELD_CUSTOM, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_OUTPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, outputname, eventFuncs }
// replaces EXPORT table for portability and non-DLL based systems (xbox)
#define DEFINE_FUNCTION_RAW( function, func_type ) { FIELD_VOID, nameHolder.GenerateName(#function), { NULL, NULL }, 1, FTYPEDESC_FUNCTIONTABLE, NULL, NULL, (inputfunc_t)((func_type)(&classNameTypedef::function)) }
#define DEFINE_FUNCTION( function ) DEFINE_FUNCTION_RAW( function, inputfunc_t )
#define FTYPEDESC_GLOBAL 0x0001 // This field is masked for global entity save/restore
#define FTYPEDESC_SAVE 0x0002 // This field is saved to disk
#define FTYPEDESC_KEY 0x0004 // This field can be requested and written to by string name at load time
#define FTYPEDESC_INPUT 0x0008 // This field can be written to by string name at run time, and a function called
#define FTYPEDESC_OUTPUT 0x0010 // This field propogates it's value to all targets whenever it changes
#define FTYPEDESC_FUNCTIONTABLE 0x0020 // This is a table entry for a member function pointer
#define FTYPEDESC_PTR 0x0040 // This field is a pointer, not an embedded object
#define FTYPEDESC_OVERRIDE 0x0080 // The field is an override for one in a base class (only used by prediction system for now)
// Flags used by other systems (e.g., prediction system)
#define FTYPEDESC_INSENDTABLE 0x0100 // This field is present in a network SendTable
#define FTYPEDESC_PRIVATE 0x0200 // The field is local to the client or server only (not referenced by prediction code and not replicated by networking)
#define FTYPEDESC_NOERRORCHECK 0x0400 // The field is part of the prediction typedescription, but doesn't get compared when checking for errors
#define FTYPEDESC_MODELINDEX 0x0800 // The field is a model index (used for debugging output)
#define FTYPEDESC_INDEX 0x1000 // The field is an index into file data, used for byteswapping.
// These flags apply to C_BasePlayer derived objects only
#define FTYPEDESC_VIEW_OTHER_PLAYER 0x2000 // By default you can only view fields on the local player (yourself),
// but if this is set, then we allow you to see fields on other players
#define FTYPEDESC_VIEW_OWN_TEAM 0x4000 // Only show this data if the player is on the same team as the local player
#define FTYPEDESC_VIEW_NEVER 0x8000 // Never show this field to anyone, even the local player (unusual)
#define TD_MSECTOLERANCE 0.001f // This is a FIELD_FLOAT and should only be checked to be within 0.001 of the networked info
struct typedescription_t;
class ISaveRestoreOps;
//
// Function prototype for all input handlers.
//
typedef void (CBaseEntity::*inputfunc_t)(inputdata_t &data);
struct datamap_t;
struct typedescription_t;
enum
{
TD_OFFSET_NORMAL = 0,
TD_OFFSET_PACKED = 1,
// Must be last
TD_OFFSET_COUNT,
};
struct typedescription_t
{
fieldtype_t fieldType;
const char *fieldName;
int fieldOffset[ TD_OFFSET_COUNT ]; // 0 == normal, 1 == packed offset
unsigned short fieldSize;
short flags;
// the name of the variable in the map/fgd data, or the name of the action
const char *externalName;
// pointer to the function set for save/restoring of custom data types
ISaveRestoreOps *pSaveRestoreOps;
// for associating function with string names
inputfunc_t inputFunc;
// For embedding additional datatables inside this one
datamap_t *td;
// Stores the actual member variable size in bytes
int fieldSizeInBytes;
// FTYPEDESC_OVERRIDE point to first baseclass instance if chains_validated has occurred
struct typedescription_t *override_field;
// Used to track exclusion of baseclass fields
int override_count;
// Tolerance for field errors for float fields
float fieldTolerance;
};
//-----------------------------------------------------------------------------
// Purpose: stores the list of objects in the hierarchy
// used to iterate through an object's data descriptions
//-----------------------------------------------------------------------------
struct datamap_t
{
typedescription_t *dataDesc;
int dataNumFields;
char const *dataClassName;
datamap_t *baseMap;
bool chains_validated;
// Have the "packed" offsets been computed
bool packed_offsets_computed;
int packed_size;
#if defined( _DEBUG )
bool bValidityChecked;
#endif // _DEBUG
};
//-----------------------------------------------------------------------------
//
// Macros used to implement datadescs
//
#define DECLARE_SIMPLE_DATADESC() \
static datamap_t m_DataMap; \
static datamap_t *GetBaseMap(); \
template <typename T> friend void DataMapAccess(T *, datamap_t **p); \
template <typename T> friend datamap_t *DataMapInit(T *);
#define DECLARE_DATADESC() \
DECLARE_SIMPLE_DATADESC() \
virtual datamap_t *GetDataDescMap( void );
#define BEGIN_DATADESC( className ) \
datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \
datamap_t *className::GetDataDescMap( void ) { return &m_DataMap; } \
datamap_t *className::GetBaseMap() { datamap_t *pResult; DataMapAccess((BaseClass *)NULL, &pResult); return pResult; } \
BEGIN_DATADESC_GUTS( className )
#define BEGIN_DATADESC_NO_BASE( className ) \
datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \
datamap_t *className::GetDataDescMap( void ) { return &m_DataMap; } \
datamap_t *className::GetBaseMap() { return NULL; } \
BEGIN_DATADESC_GUTS( className )
#define BEGIN_SIMPLE_DATADESC( className ) \
datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \
datamap_t *className::GetBaseMap() { return NULL; } \
BEGIN_DATADESC_GUTS( className )
#define BEGIN_SIMPLE_DATADESC_( className, BaseClass ) \
datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \
datamap_t *className::GetBaseMap() { datamap_t *pResult; DataMapAccess((BaseClass *)NULL, &pResult); return pResult; } \
BEGIN_DATADESC_GUTS( className )
#define BEGIN_DATADESC_GUTS( className ) \
template <typename T> datamap_t *DataMapInit(T *); \
template <> datamap_t *DataMapInit<className>( className * ); \
namespace className##_DataDescInit \
{ \
datamap_t *g_DataMapHolder = DataMapInit( (className *)NULL ); /* This can/will be used for some clean up duties later */ \
} \
\
template <> datamap_t *DataMapInit<className>( className * ) \
{ \
typedef className classNameTypedef; \
static CDatadescGeneratedNameHolder nameHolder(#className); \
className::m_DataMap.baseMap = className::GetBaseMap(); \
static typedescription_t dataDesc[] = \
{ \
{ FIELD_VOID,0, {0,0},0,0,0,0,0,0}, /* so you can define "empty" tables */
#define END_DATADESC() \
}; \
\
if ( sizeof( dataDesc ) > sizeof( dataDesc[0] ) ) \
{ \
classNameTypedef::m_DataMap.dataNumFields = SIZE_OF_ARRAY( dataDesc ) - 1; \
classNameTypedef::m_DataMap.dataDesc = &dataDesc[1]; \
} \
else \
{ \
classNameTypedef::m_DataMap.dataNumFields = 1; \
classNameTypedef::m_DataMap.dataDesc = dataDesc; \
} \
return &classNameTypedef::m_DataMap; \
}
// used for when there is no data description
#define IMPLEMENT_NULL_SIMPLE_DATADESC( derivedClass ) \
BEGIN_SIMPLE_DATADESC( derivedClass ) \
END_DATADESC()
#define IMPLEMENT_NULL_SIMPLE_DATADESC_( derivedClass, baseClass ) \
BEGIN_SIMPLE_DATADESC_( derivedClass, baseClass ) \
END_DATADESC()
#define IMPLEMENT_NULL_DATADESC( derivedClass ) \
BEGIN_DATADESC( derivedClass ) \
END_DATADESC()
// helps get the offset of a bitfield
#define BEGIN_BITFIELD( name ) \
union \
{ \
char name; \
struct \
{
#define END_BITFIELD() \
}; \
};
//-----------------------------------------------------------------------------
// Forward compatability with potential seperate byteswap datadescs
#define DECLARE_BYTESWAP_DATADESC() DECLARE_SIMPLE_DATADESC()
#define BEGIN_BYTESWAP_DATADESC(name) BEGIN_SIMPLE_DATADESC(name)
#define BEGIN_BYTESWAP_DATADESC_(name,base) BEGIN_SIMPLE_DATADESC_(name,base)
#define END_BYTESWAP_DATADESC() END_DATADESC()
//-----------------------------------------------------------------------------
template <typename T>
inline void DataMapAccess(T *ignored, datamap_t **p)
{
*p = &T::m_DataMap;
}
//-----------------------------------------------------------------------------
class CDatadescGeneratedNameHolder
{
public:
CDatadescGeneratedNameHolder( const char *pszBase )
: m_pszBase(pszBase)
{
m_nLenBase = strlen( m_pszBase );
}
~CDatadescGeneratedNameHolder()
{
for ( int i = 0; i < m_Names.Count(); i++ )
{
delete m_Names[i];
}
}
const char *GenerateName( const char *pszIdentifier )
{
char *pBuf = new char[m_nLenBase + strlen(pszIdentifier) + 1];
strcpy( pBuf, m_pszBase );
strcat( pBuf, pszIdentifier );
m_Names.AddToTail( pBuf );
return pBuf;
}
private:
const char *m_pszBase;
size_t m_nLenBase;
CUtlVector<char *> m_Names;
};
//-----------------------------------------------------------------------------
#include "tier0/memdbgoff.h"
#endif // DATAMAP_H

View File

@ -0,0 +1,35 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef ATTRIBUTEFLAGS_H
#define ATTRIBUTEFLAGS_H
#ifdef _WIN32
#pragma once
#endif
enum
{
// NOTE: The first 5 flags bits are reserved for attribute type
FATTRIB_TYPEMASK = 0x1F,
FATTRIB_READONLY = (1<<5), // Don't allow editing value in editors
FATTRIB_DONTSAVE = (1<<6), // Don't persist to .dmx file
FATTRIB_DIRTY = (1<<7), // Indicates the attribute has been changed since the resolve phase
FATTRIB_HAS_CALLBACK = (1<<8), // Indicates that this will notify its owner and/or other elements when it changes
FATTRIB_EXTERNAL = (1<<9), // Indicates this attribute's data is externally owned (in a CDmElement somewhere)
FATTRIB_TOPOLOGICAL = (1<<10), // Indicates this attribute effects the scene's topology (ie it's an attribute name or element)
FATTRIB_MUSTCOPY = (1<<11), // parent element must make a new copy during CopyInto, even for shallow copy
FATTRIB_NEVERCOPY = (1<<12), // parent element shouldn't make a new copy during CopyInto, even for deep copy
FATTRIB_STANDARD = (1<<13), // This flag is set if it's a "standard" attribute, namely "name"
FATTRIB_USERDEFINED = (1<<14), // This flag is used to sort attributes in the element properties view. User defined flags come last.
FATTRIB_NODUPLICATES = (1<<15),// For element array types, disallows duplicate values from being inserted into the array.
FATTRIB_HAS_ARRAY_CALLBACK = (1<<16), // Indicates that this will notify its owner and/or other elements array elements changes. Note that when elements shift (say, inserting at head, or fast remove), callbacks are not executed for these elements.
FATTRIB_HAS_PRE_CALLBACK = (1<<17), // Indicates that this will notify its owner and/or other elements right before it changes
FATTRIB_OPERATOR_DIRTY = (1<<18),// Used and cleared only by operator phase of datamodel
};
#endif // ATTRIBUTEFLAGS_H

View File

@ -0,0 +1,768 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef DMATTRIBUTE_H
#define DMATTRIBUTE_H
#ifdef _WIN32
#pragma once
#endif
#include "datamodel/attributeflags.h"
#include "datamodel/idatamodel.h"
#include "datamodel/dmattributetypes.h"
#include "datamodel/dmelement.h"
#include "datamodel/dmvar.h"
#include "tier1/utlhash.h"
//-----------------------------------------------------------------------------
// Fast dynamic cast
//-----------------------------------------------------------------------------
template< class E >
inline E *CastElement( CDmElement *pElement )
{
if ( pElement && pElement->IsA( E::GetStaticTypeSymbol() ) )
return static_cast< E* >( pElement );
return NULL;
}
//-----------------------------------------------------------------------------
// type-safe element creation and accessor helpers - infers type name string from actual type
//-----------------------------------------------------------------------------
template< class E >
inline E *GetElement( DmElementHandle_t hElement )
{
CDmElement *pElement = g_pDataModel->GetElement( hElement );
return CastElement< E >( pElement );
}
//-----------------------------------------------------------------------------
// Typesafe element creation + destruction
//-----------------------------------------------------------------------------
template< class E >
inline E *CreateElement( const char *pObjectName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL )
{
return GetElement< E >( g_pDataModel->CreateElement( E::GetStaticTypeSymbol(), pObjectName, fileid, pObjectID ) );
}
template< class E >
inline E *CreateElement( const char *pElementType, const char *pObjectName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL )
{
return GetElement< E >( g_pDataModel->CreateElement( pElementType, pObjectName, fileid, pObjectID ) );
}
//-----------------------------------------------------------------------------
// Used for attribute change callbacks
//-----------------------------------------------------------------------------
typedef unsigned short DmMailingList_t;
enum
{
DMMAILINGLIST_INVALID = (DmMailingList_t)~0
};
//-----------------------------------------------------------------------------
// Purpose: A general purpose pAttribute. Eventually will be extensible to arbitrary user types
//-----------------------------------------------------------------------------
class CDmAttribute
{
public:
// Returns the type
DmAttributeType_t GetType() const;
const char *GetTypeString() const;
template< class T > bool IsA() const;
// Returns the name. NOTE: The utlsymbol
// can be turned into a string by using g_pDataModel->String();
const char *GetName() const;
UtlSymId_t GetNameSymbol() const;
void SetName( const char *newName );
// Gets the attribute value
// NOTE: GetValueUntyped is used with GetType() for use w/ SetValue( type, void* )
template< class T > const T& GetValue() const;
template< class T > const T& GetValue( const T& defaultValue ) const;
const char *GetValueString() const;
template< class E > E *GetValueElement() const;
const void *GetValueUntyped() const;
// Sets the attribute value
template< class T > void SetValue( const T &value );
template< class E > void SetValue( E* pValue );
void SetValue( const void *pValue, size_t nSize );
// Copies w/ type conversion (if possible) from another attribute
void SetValue( const CDmAttribute *pAttribute );
void SetValue( CDmAttribute *pAttribute );
void SetValue( DmAttributeType_t valueType, const void *pValue );
// Sets the attribute to its default value based on its type
void SetToDefaultValue();
// Convert to and from string
void SetValueFromString( const char *pValue );
const char *GetValueAsString( char *pBuffer, size_t nBufLen ) const;
// Used for element and element array attributes; it specifies which type of
// elements are valid to be referred to by this attribute
void SetElementTypeSymbol( UtlSymId_t typeSymbol );
UtlSymId_t GetElementTypeSymbol() const;
// Returns the next attribute
CDmAttribute *NextAttribute();
const CDmAttribute *NextAttribute() const;
// Returns the owner
CDmElement *GetOwner();
// Methods related to flags
void AddFlag( int flags );
void RemoveFlag( int flags );
void ClearFlags();
int GetFlags() const;
bool IsFlagSet( int flags ) const;
// Serialization
bool Serialize( CUtlBuffer &buf ) const;
bool Unserialize( CUtlBuffer &buf );
// Serialization of a single element.
// First version of UnserializeElement adds to tail if it worked
// Second version overwrites, but does not add, the element at the specified index
bool SerializeElement( int nElement, CUtlBuffer &buf ) const;
bool UnserializeElement( CUtlBuffer &buf );
bool UnserializeElement( int nElement, CUtlBuffer &buf );
// Does this attribute serialize on multiple lines?
bool SerializesOnMultipleLines() const;
// Get the attribute/create an attribute handle
DmAttributeHandle_t GetHandle( bool bCreate = true );
// Notify external elements upon change ( Calls OnAttributeChanged )
// Pass false here to stop notification
void NotifyWhenChanged( DmElementHandle_t h, bool bNotify );
// estimate memory overhead
int EstimateMemoryUsage( TraversalDepth_t depth ) const;
private:
// Class factory
static CDmAttribute *CreateAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName );
static CDmAttribute *CreateExternalAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName, void *pExternalMemory );
static void DestroyAttribute( CDmAttribute *pAttribute );
// Constructor, destructor
CDmAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName );
CDmAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName, void *pMemory );
~CDmAttribute();
// Used when constructing CDmAttributes
void Init( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName );
// Used when shutting down, indicates DmAttributeHandle_t referring to this are invalid
void InvalidateHandle();
// Used when shutting down, indicates no more change notifications will be sent to listening elements
void CleanupMailingList();
// Called when the attribute changes
void PreChanged();
void OnChanged( bool bArrayCountChanged = false, bool bIsTopological = false );
// Is modification allowed in this phase?
bool ModificationAllowed() const;
// Mark the attribute as being dirty
bool MarkDirty();
// Is the data inline in a containing element class?
bool IsDataInline() const;
// Allocates, frees internal data storage
void CreateAttributeData();
void DeleteAttributeData();
// Gets at the internal data storage
void* GetAttributeData();
const void* GetAttributeData() const;
template < class T > typename CDmAttributeInfo< T >::StorageType_t* GetData();
template < class T > const typename CDmAttributeInfo< T >::StorageType_t* GetData() const;
template < class T > typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* GetArrayData();
template < class T > const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* GetArrayData() const;
// Used by CDmElement to manage the list of attributes it owns
CDmAttribute **GetNextAttributeRef();
// Implementational function used for memory consumption estimation computation
int EstimateMemoryUsageInternal( CUtlHash< DmElementHandle_t > &visited, TraversalDepth_t depth, int *pCategories ) const;
// Called by elements after unserialization of their attributes is complete
void OnUnserializationFinished();
template< class T > bool IsTypeConvertable() const;
template< class T > bool ShouldModify( const T& src );
template< class T > void CopyData( const T& src );
template< class T > void CopyDataOut( T& dest ) const;
private:
CDmAttribute *m_pNext;
void *m_pData;
CDmElement *m_pOwner;
int m_nFlags;
DmAttributeHandle_t m_Handle;
CUtlSymbol m_Name;
DmMailingList_t m_hMailingList;
friend class CDmElement;
friend class CDmAttributeAccessor;
template< class T > friend class CDmrElementArray;
template< class E > friend class CDmrElementArrayConst;
template< class T > friend class CDmaArrayAccessor;
template< class T, class B > friend class CDmrDecorator;
template< class T, class B > friend class CDmrDecoratorConst;
template< class T > friend class CDmArrayAttributeOp;
};
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline DmAttributeType_t CDmAttribute::GetType() const
{
return (DmAttributeType_t)( m_nFlags & FATTRIB_TYPEMASK );
}
template< class T > inline bool CDmAttribute::IsA() const
{
return GetType() == CDmAttributeInfo< T >::AttributeType();
}
inline const char *CDmAttribute::GetName() const
{
return g_pDataModel->GetString( m_Name );
}
inline UtlSymId_t CDmAttribute::GetNameSymbol() const
{
return m_Name;
}
//-----------------------------------------------------------------------------
// Iteration
//-----------------------------------------------------------------------------
inline CDmAttribute *CDmAttribute::NextAttribute()
{
return m_pNext;
}
inline const CDmAttribute *CDmAttribute::NextAttribute() const
{
return m_pNext;
}
//-----------------------------------------------------------------------------
// Returns the owner
//-----------------------------------------------------------------------------
inline CDmElement *CDmAttribute::GetOwner()
{
return m_pOwner;
}
//-----------------------------------------------------------------------------
// Value getting methods
//-----------------------------------------------------------------------------
template< class T >
inline const T& CDmAttribute::GetValue( const T& defaultValue ) const
{
if ( GetType() == ( DmAttributeType_t )( CDmAttributeInfo< T >::ATTRIBUTE_TYPE ) )
return *reinterpret_cast< const T* >( m_pData );
if ( IsTypeConvertable< T >() )
{
static T tempVal;
CopyDataOut( tempVal );
return tempVal;
}
Assert( 0 );
return defaultValue;
}
template< class T >
inline const T& CDmAttribute::GetValue() const
{
static CDmaVar< T > defaultVal;
return GetValue( defaultVal.Get() );
}
inline const char *CDmAttribute::GetValueString() const
{
Assert( GetType() == AT_STRING );
if ( GetType() != AT_STRING )
return NULL;
return GetValue< CUtlString >();
}
// used with GetType() for use w/ SetValue( type, void* )
inline const void* CDmAttribute::GetValueUntyped() const
{
return m_pData;
}
template< class E >
inline E* CDmAttribute::GetValueElement() const
{
Assert( GetType() == AT_ELEMENT );
if ( GetType() == AT_ELEMENT )
return GetElement<E>( this->GetValue< DmElementHandle_t >() );
return NULL;
}
//-----------------------------------------------------------------------------
// Value setting methods
//-----------------------------------------------------------------------------
template< class E >
inline void CDmAttribute::SetValue( E* pValue )
{
Assert( GetType() == AT_ELEMENT );
if ( GetType() == AT_ELEMENT )
{
SetValue( pValue ? pValue->GetHandle() : DMELEMENT_HANDLE_INVALID );
}
}
template<>
inline void CDmAttribute::SetValue( const char *pValue )
{
int nLen = pValue ? Q_strlen( pValue ) + 1 : 0;
CUtlString str( pValue, nLen );
return SetValue( str );
}
template<>
inline void CDmAttribute::SetValue( char *pValue )
{
return SetValue( (const char *)pValue );
}
inline void CDmAttribute::SetValue( const void *pValue, size_t nSize )
{
CUtlBinaryBlock buf( pValue, nSize );
return SetValue( buf );
}
//-----------------------------------------------------------------------------
// Methods related to flags
//-----------------------------------------------------------------------------
inline void CDmAttribute::AddFlag( int nFlags )
{
m_nFlags |= nFlags;
}
inline void CDmAttribute::RemoveFlag( int nFlags )
{
m_nFlags &= ~nFlags;
}
inline void CDmAttribute::ClearFlags()
{
m_nFlags = 0;
}
inline int CDmAttribute::GetFlags() const
{
return m_nFlags;
}
inline bool CDmAttribute::IsFlagSet( int nFlags ) const
{
return ( nFlags & m_nFlags ) ? true : false;
}
inline bool CDmAttribute::IsDataInline() const
{
return !IsFlagSet(FATTRIB_EXTERNAL);
}
//-----------------------------------------------------------------------------
// Gets at the internal data storage
//-----------------------------------------------------------------------------
inline void* CDmAttribute::GetAttributeData()
{
return m_pData;
}
inline const void* CDmAttribute::GetAttributeData() const
{
return m_pData;
}
template < class T >
inline typename CDmAttributeInfo< T >::StorageType_t* CDmAttribute::GetData()
{
return ( typename CDmAttributeInfo< T >::StorageType_t* )m_pData;
}
template < class T >
inline typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* CDmAttribute::GetArrayData()
{
return ( typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* )m_pData;
}
template < class T >
inline const typename CDmAttributeInfo< T >::StorageType_t* CDmAttribute::GetData() const
{
return ( const typename CDmAttributeInfo< T >::StorageType_t* )m_pData;
}
template < class T >
inline const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* CDmAttribute::GetArrayData() const
{
return ( const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* )m_pData;
}
//-----------------------------------------------------------------------------
// Used by CDmElement to manage the list of attributes it owns
//-----------------------------------------------------------------------------
inline CDmAttribute **CDmAttribute::GetNextAttributeRef()
{
return &m_pNext;
}
//-----------------------------------------------------------------------------
// helper function for determining which attributes/elements to traverse during copy/find/save/etc.
//-----------------------------------------------------------------------------
inline bool ShouldTraverse( const CDmAttribute *pAttr, TraversalDepth_t depth )
{
switch ( depth )
{
case TD_NONE:
return false;
case TD_SHALLOW:
if ( !pAttr->IsFlagSet( FATTRIB_MUSTCOPY ) )
return false;
// fall-through intentional
case TD_DEEP:
if ( pAttr->IsFlagSet( FATTRIB_NEVERCOPY ) )
return false;
// fall-through intentional
case TD_ALL:
return true;
}
Assert( 0 );
return false;
}
//-----------------------------------------------------------------------------
// Gets attributes
//-----------------------------------------------------------------------------
inline CDmAttribute *CDmElement::GetAttribute( const char *pAttributeName, DmAttributeType_t type )
{
CDmAttribute *pAttribute = FindAttribute( pAttributeName );
if ( ( type != AT_UNKNOWN ) && pAttribute && ( pAttribute->GetType() != type ) )
return NULL;
return pAttribute;
}
inline const CDmAttribute *CDmElement::GetAttribute( const char *pAttributeName, DmAttributeType_t type ) const
{
CDmAttribute *pAttribute = FindAttribute( pAttributeName );
if ( ( type != AT_UNKNOWN ) && pAttribute && ( pAttribute->GetType() != type ) )
return NULL;
return pAttribute;
}
//-----------------------------------------------------------------------------
// AddAttribute calls
//-----------------------------------------------------------------------------
inline CDmAttribute *CDmElement::AddAttribute( const char *pAttributeName, DmAttributeType_t type )
{
CDmAttribute *pAttribute = FindAttribute( pAttributeName );
if ( pAttribute )
return ( pAttribute->GetType() == type ) ? pAttribute : NULL;
pAttribute = CreateAttribute( pAttributeName, type );
return pAttribute;
}
template< class E > inline CDmAttribute *CDmElement::AddAttributeElement( const char *pAttributeName )
{
CDmAttribute *pAttribute = AddAttribute( pAttributeName, AT_ELEMENT );
if ( !pAttribute )
return NULL;
// FIXME: If the attribute exists but has a different element type symbol, should we complain?
pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() );
return pAttribute;
}
template< class E > inline CDmAttribute *CDmElement::AddAttributeElementArray( const char *pAttributeName )
{
CDmAttribute *pAttribute = AddAttribute( pAttributeName, AT_ELEMENT_ARRAY );
if ( !pAttribute )
return NULL;
// FIXME: If the attribute exists but has a different element type symbol, should we complain?
pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() );
return pAttribute;
}
//-----------------------------------------------------------------------------
// GetValue methods
//-----------------------------------------------------------------------------
template< class T >
inline const T& CDmElement::GetValue( const char *pAttributeName ) const
{
static CDmaVar<T> defaultVal;
return GetValue( pAttributeName, defaultVal.Get() );
}
inline const char *CDmElement::GetValueString( const char *pAttributeName ) const
{
return GetValue<CUtlString>( pAttributeName ).Get();
}
template< class E >
inline E* CDmElement::GetValueElement( const char *pAttributeName ) const
{
DmElementHandle_t h = GetValue< DmElementHandle_t >( pAttributeName );
return GetElement<E>( h );
}
template< class T >
inline const T& CDmElement::GetValue( const char *pAttributeName, const T& defaultVal ) const
{
const CDmAttribute *pAttribute = FindAttribute( pAttributeName );
if ( pAttribute != NULL )
return pAttribute->GetValue<T>();
return defaultVal;
}
//-----------------------------------------------------------------------------
// SetValue methods
//-----------------------------------------------------------------------------
template< class T >
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const T& value )
{
CDmAttribute *pAttribute = FindAttribute( pAttributeName );
if ( !pAttribute )
{
pAttribute = CreateAttribute( pAttributeName, CDmAttributeInfo<T>::AttributeType() );
}
if ( pAttribute )
{
pAttribute->SetValue( value );
return pAttribute;
}
return NULL;
}
template< class E >
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, E* pElement )
{
DmElementHandle_t hElement = pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID;
return SetValue( pAttributeName, hElement );
}
template<>
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const char *pValue )
{
int nLen = pValue ? Q_strlen( pValue ) + 1 : 0;
CUtlString str( pValue, nLen );
return SetValue( pAttributeName, str );
}
template<>
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, char *pValue )
{
return SetValue( pAttributeName, (const char *)pValue );
}
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const void *pValue, size_t nSize )
{
CUtlBinaryBlock buf( pValue, nSize );
return SetValue( pAttributeName, buf );
}
//-----------------------------------------------------------------------------
// AddValue methods( set value if not found )
//-----------------------------------------------------------------------------
template< class T >
inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, const T& value )
{
CDmAttribute *pAttribute = GetAttribute( pAttributeName );
if ( !pAttribute )
return SetValue( pAttributeName, value );
return pAttribute;
}
template< class E >
inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, E* pElement )
{
DmElementHandle_t hElement = pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID;
return InitValue( pAttributeName, hElement );
}
inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, const void *pValue, size_t size )
{
CDmAttribute *pAttribute = GetAttribute( pAttributeName );
if ( !pAttribute )
return SetValue( pAttributeName, pValue, size );
return pAttribute;
}
template< class T >
T *FindReferringElement( CDmElement *pElement, UtlSymId_t symAttrName, bool bMustBeInSameFile = true )
{
DmAttributeReferenceIterator_t i = g_pDataModel->FirstAttributeReferencingElement( pElement->GetHandle() );
while ( i != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID )
{
CDmAttribute *pAttribute = g_pDataModel->GetAttribute( i );
CDmElement *pDmeParent = pAttribute->GetOwner();
if ( pDmeParent && pAttribute->GetNameSymbol() == symAttrName )
{
T *pParent = CastElement< T >( pDmeParent );
if ( pParent )
{
if ( !bMustBeInSameFile || ( pParent->GetFileId() == pElement->GetFileId() ) )
return pParent;
}
}
i = g_pDataModel->NextAttributeReferencingElement( i );
}
return NULL;
}
template< class T >
T *FindAncestorReferencingElement( CDmElement *target )
{
if ( !target )
return NULL;
for ( DmAttributeReferenceIterator_t it = g_pDataModel->FirstAttributeReferencingElement( target->GetHandle() );
it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
it = g_pDataModel->NextAttributeReferencingElement( it ) )
{
CDmAttribute *attr = g_pDataModel->GetAttribute( it );
Assert( attr );
CDmElement *element = attr->GetOwner();
Assert( element );
if ( !element )
continue;
T *t = CastElement< T >( element );
if ( !t )
continue;
return t;
}
return NULL;
}
template< class T >
T *FindAncestorReferencingElement_R_Impl( CUtlRBTree< CDmElement * >& visited, CDmElement *check )
{
if ( visited.Find( check ) != visited.InvalidIndex() )
return NULL;
visited.Insert( check );
// Pass one, see if it's in this ancestor list
DmAttributeReferenceIterator_t it;
for ( it = g_pDataModel->FirstAttributeReferencingElement( check->GetHandle() );
it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
it = g_pDataModel->NextAttributeReferencingElement( it ) )
{
CDmAttribute *attr = g_pDataModel->GetAttribute( it );
Assert( attr );
CDmElement *element = attr->GetOwner();
Assert( element );
if ( !element )
continue;
T *t = CastElement< T >( element );
if ( !t )
continue;
return t;
}
for ( it = g_pDataModel->FirstAttributeReferencingElement( check->GetHandle() );
it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
it = g_pDataModel->NextAttributeReferencingElement( it ) )
{
CDmAttribute *attr = g_pDataModel->GetAttribute( it );
Assert( attr );
CDmElement *element = attr->GetOwner();
Assert( element );
if ( !element )
continue;
T *found = FindAncestorReferencingElement_R_Impl< T >( visited, element );
if ( found )
return found;
}
return NULL;
}
template< class T >
void FindAncestorsReferencingElement( CDmElement *target, CUtlVector< T* >& list )
{
if ( !target )
return;
list.RemoveAll();
for ( DmAttributeReferenceIterator_t it = g_pDataModel->FirstAttributeReferencingElement( target->GetHandle() );
it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
it = g_pDataModel->NextAttributeReferencingElement( it ) )
{
CDmAttribute *attr = g_pDataModel->GetAttribute( it );
Assert( attr );
CDmElement *element = attr->GetOwner();
Assert( element );
if ( !element )
continue;
T* t = CastElement< T >( element );
if ( !t )
continue;
if ( list.Find( t ) != list.InvalidIndex() )
continue;
list.AddToTail( t );
}
}
template< class T >
T *FindAncestorReferencingElement_R( CDmElement *target )
{
if ( !target )
return NULL;
CUtlRBTree< CDmElement * > visited( 0, 0, DefLessFunc( CDmElement * ) );
return FindAncestorReferencingElement_R_Impl< T >( visited, target );
}
#endif // DMATTRIBUTE_H

View File

@ -0,0 +1,316 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef DMATTRIBUTETYPES_H
#define DMATTRIBUTETYPES_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utlvector.h"
#include "tier1/utlstring.h"
#include "tier1/uniqueid.h"
#include "Color.h"
#include "mathlib/vector2d.h"
#include "mathlib/vector.h"
#include "mathlib/vector4d.h"
#include "mathlib/vmatrix.h"
#include "datamodel/dmelementhandle.h"
#include "tier1/utlsymbol.h"
//-----------------------------------------------------------------------------
// Object Id
//-----------------------------------------------------------------------------
typedef UniqueId_t DmObjectId_t;
//-----------------------------------------------------------------------------
// Necessary for template specialization for AT_UNKNOWN
//-----------------------------------------------------------------------------
struct DmUnknownAttribute_t
{
bool operator==( const DmUnknownAttribute_t& src ) const { return true; }
};
//-----------------------------------------------------------------------------
// Element array
//-----------------------------------------------------------------------------
struct DmElementAttribute_t
{
DmElementAttribute_t() : m_ElementType( UTL_INVAL_SYMBOL ) {}
operator DmElementHandle_t&() { return m_Handle; }
operator const DmElementHandle_t&() const { return m_Handle; }
DmElementHandle_t m_Handle;
UtlSymId_t m_ElementType;
};
struct DmElementArray_t : public CUtlVector< DmElementHandle_t >
{
DmElementArray_t() : m_ElementType( UTL_INVAL_SYMBOL ) {}
UtlSymId_t m_ElementType;
};
//-----------------------------------------------------------------------------
// Attribute chunk type enum
//-----------------------------------------------------------------------------
enum DmAttributeType_t
{
AT_UNKNOWN = 0,
AT_FIRST_VALUE_TYPE,
AT_ELEMENT = AT_FIRST_VALUE_TYPE,
AT_INT,
AT_FLOAT,
AT_BOOL,
AT_STRING,
AT_VOID,
AT_OBJECTID,
AT_COLOR, //rgba
AT_VECTOR2,
AT_VECTOR3,
AT_VECTOR4,
AT_QANGLE,
AT_QUATERNION,
AT_VMATRIX,
AT_FIRST_ARRAY_TYPE,
AT_ELEMENT_ARRAY = AT_FIRST_ARRAY_TYPE,
AT_INT_ARRAY,
AT_FLOAT_ARRAY,
AT_BOOL_ARRAY,
AT_STRING_ARRAY,
AT_VOID_ARRAY,
AT_OBJECTID_ARRAY,
AT_COLOR_ARRAY,
AT_VECTOR2_ARRAY,
AT_VECTOR3_ARRAY,
AT_VECTOR4_ARRAY,
AT_QANGLE_ARRAY,
AT_QUATERNION_ARRAY,
AT_VMATRIX_ARRAY,
AT_TYPE_COUNT,
};
const char *GetTypeString( DmAttributeType_t type );
inline bool IsValueType( DmAttributeType_t type )
{
return type >= AT_FIRST_VALUE_TYPE && type < AT_FIRST_ARRAY_TYPE;
}
inline bool IsArrayType( DmAttributeType_t type )
{
return type >= AT_FIRST_ARRAY_TYPE && type < AT_TYPE_COUNT;
}
inline bool IsTopological( DmAttributeType_t type )
{
return type == AT_ELEMENT || type == AT_ELEMENT_ARRAY;
}
inline DmAttributeType_t ValueTypeToArrayType( DmAttributeType_t type )
{
Assert( IsValueType( type ) );
return ( DmAttributeType_t )( ( type - AT_FIRST_VALUE_TYPE ) + AT_FIRST_ARRAY_TYPE );
}
inline DmAttributeType_t ArrayTypeToValueType( DmAttributeType_t type )
{
Assert( IsArrayType( type ) );
return ( DmAttributeType_t )( ( type - AT_FIRST_ARRAY_TYPE ) + AT_FIRST_VALUE_TYPE );
}
inline int NumComponents( DmAttributeType_t type )
{
switch ( type )
{
case AT_BOOL:
case AT_INT:
case AT_FLOAT:
return 1;
case AT_VECTOR2:
return 2;
case AT_VECTOR3:
case AT_QANGLE:
return 3;
case AT_COLOR: //rgba
case AT_VECTOR4:
case AT_QUATERNION:
return 4;
case AT_VMATRIX:
return 16;
case AT_ELEMENT:
case AT_STRING:
case AT_VOID:
case AT_OBJECTID:
default:
return 0;
}
}
template< typename T >
inline float GetComponent( const T &value, int i )
{
Assert( 0 );
return 0.0f;
}
template <> inline float GetComponent( const bool &value, int i )
{
Assert( i == 0 );
return value ? 1.0f : 0.0f;
}
template <> inline float GetComponent( const int &value, int i )
{
Assert( i == 0 );
return float( value );
}
template <> inline float GetComponent( const float &value, int i )
{
Assert( i == 0 );
return value;
}
template <> inline float GetComponent( const Vector2D &value, int i )
{
return value[ i ];
}
template <> inline float GetComponent( const Vector &value, int i )
{
return value[ i ];
}
template <> inline float GetComponent( const QAngle &value, int i )
{
return value[ i ];
}
template <> inline float GetComponent( const Color &value, int i )
{
return value[ i ];
}
template <> inline float GetComponent( const Vector4D &value, int i )
{
return value[ i ];
}
template <> inline float GetComponent( const Quaternion &value, int i )
{
return value[ i ];
}
template <> inline float GetComponent( const VMatrix &value, int i )
{
return value.Base()[ i ];
}
//-----------------------------------------------------------------------------
// Attribute info...
//-----------------------------------------------------------------------------
template <typename T>
class CDmAttributeInfo
{
public:
enum { ATTRIBUTE_TYPE = AT_UNKNOWN };
typedef T StorageType_t;
static DmAttributeType_t AttributeType()
{
return AT_UNKNOWN;
}
static const char *AttributeTypeName()
{
return "unknown";
}
static void SetDefaultValue( T& value )
{
Assert(0);
}
};
#define DECLARE_ATTRIBUTE_TYPE_INTERNAL( _className, _storageType, _attributeType, _attributeName, _defaultSetStatement ) \
template< > class CDmAttributeInfo< _className > \
{ \
public: \
enum { ATTRIBUTE_TYPE = _attributeType }; \
typedef _storageType StorageType_t; \
static DmAttributeType_t AttributeType() { return _attributeType; } \
static const char *AttributeTypeName() { return _attributeName; } \
static void SetDefaultValue( _className& value ) { _defaultSetStatement } \
}; \
#define DECLARE_ATTRIBUTE_ARRAY_TYPE_INTERNAL( _className, _storageType, _attributeType, _attributeName ) \
template< > class CDmAttributeInfo< CUtlVector<_className> > \
{ \
public: \
enum { ATTRIBUTE_TYPE = _attributeType }; \
typedef _storageType StorageType_t; \
static DmAttributeType_t AttributeType() { return _attributeType; } \
static const char *AttributeTypeName() { return _attributeName; } \
static void SetDefaultValue( CUtlVector< _className >& value ) { value.RemoveAll(); } \
}; \
#define DECLARE_ATTRIBUTE_TYPE( _className, _attributeType, _attributeName, _defaultSetStatement ) \
DECLARE_ATTRIBUTE_TYPE_INTERNAL( _className, _className, _attributeType, _attributeName, _defaultSetStatement )
#define DECLARE_ATTRIBUTE_ARRAY_TYPE( _className, _attributeType, _attributeName )\
DECLARE_ATTRIBUTE_ARRAY_TYPE_INTERNAL( _className, CUtlVector< _className >, _attributeType, _attributeName )
// NOTE: If you add an attribute type here, also add it to the list of DEFINE_ATTRIBUTE_TYPES in dmattribute.cpp
DECLARE_ATTRIBUTE_TYPE( int, AT_INT, "int", value = 0; )
DECLARE_ATTRIBUTE_TYPE( float, AT_FLOAT, "float", value = 0.0f; )
DECLARE_ATTRIBUTE_TYPE( bool, AT_BOOL, "bool", value = false; )
DECLARE_ATTRIBUTE_TYPE( Color, AT_COLOR, "color", value.SetColor( 0, 0, 0, 255 ); )
DECLARE_ATTRIBUTE_TYPE( Vector2D, AT_VECTOR2, "vector2", value.Init( 0.0f, 0.0f ); )
DECLARE_ATTRIBUTE_TYPE( Vector, AT_VECTOR3, "vector3", value.Init( 0.0f, 0.0f, 0.0f ); )
DECLARE_ATTRIBUTE_TYPE( Vector4D, AT_VECTOR4, "vector4", value.Init( 0.0f, 0.0f, 0.0f, 0.0f ); )
DECLARE_ATTRIBUTE_TYPE( QAngle, AT_QANGLE, "qangle", value.Init( 0.0f, 0.0f, 0.0f ); )
DECLARE_ATTRIBUTE_TYPE( Quaternion, AT_QUATERNION, "quaternion", value.Init( 0.0f, 0.0f, 0.0f, 1.0f ); )
DECLARE_ATTRIBUTE_TYPE( VMatrix, AT_VMATRIX, "matrix", MatrixSetIdentity( value ); )
DECLARE_ATTRIBUTE_TYPE( CUtlString, AT_STRING, "string", value.Set( NULL ); )
DECLARE_ATTRIBUTE_TYPE( CUtlBinaryBlock, AT_VOID, "binary", value.Set( NULL, 0 ); )
DECLARE_ATTRIBUTE_TYPE( DmObjectId_t, AT_OBJECTID, "elementid", InvalidateUniqueId( &value ); )
DECLARE_ATTRIBUTE_TYPE_INTERNAL( DmElementHandle_t, DmElementAttribute_t, AT_ELEMENT, "element", value = DMELEMENT_HANDLE_INVALID; )
DECLARE_ATTRIBUTE_ARRAY_TYPE( int, AT_INT_ARRAY, "int_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( float, AT_FLOAT_ARRAY, "float_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( bool, AT_BOOL_ARRAY, "bool_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( Color, AT_COLOR_ARRAY, "color_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( Vector2D, AT_VECTOR2_ARRAY, "vector2_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( Vector, AT_VECTOR3_ARRAY, "vector3_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( Vector4D, AT_VECTOR4_ARRAY, "vector4_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( QAngle, AT_QANGLE_ARRAY, "qangle_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( Quaternion, AT_QUATERNION_ARRAY, "quaternion_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( VMatrix, AT_VMATRIX_ARRAY, "matrix_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( CUtlString, AT_STRING_ARRAY, "string_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( CUtlBinaryBlock, AT_VOID_ARRAY, "binary_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE( DmObjectId_t, AT_OBJECTID_ARRAY, "elementid_array" )
DECLARE_ATTRIBUTE_ARRAY_TYPE_INTERNAL( DmElementHandle_t, DmElementArray_t, AT_ELEMENT_ARRAY, "element_array" )
#endif // DMATTRIBUTETYPES_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,243 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef DMEHANDLE_H
#define DMEHANDLE_H
#ifdef _WIN32
#pragma once
#endif
#include "datamodel/idatamodel.h"
#include "datamodel/dmelement.h"
#include "datamodel/dmattribute.h"
#include "datamodel/dmattributevar.h"
//-----------------------------------------------------------------------------
// Purpose: CDmeHandle is a templatized wrapper around DmElementHandle_t
//-----------------------------------------------------------------------------
template< class DmeType, bool Counted = false >
class CDmeHandle : public CDmeElementRefHelper
{
public:
CDmeHandle() : m_handle( DMELEMENT_HANDLE_INVALID )
{
}
explicit CDmeHandle( CDmElement *pObject ) : m_handle( DMELEMENT_HANDLE_INVALID )
{
Set( pObject );
}
CDmeHandle( DmElementHandle_t h ) : m_handle( DMELEMENT_HANDLE_INVALID )
{
Set( h );
}
CDmeHandle( const CDmeHandle< DmeType, Counted > &handle ) : m_handle( DMELEMENT_HANDLE_INVALID )
{
Set( handle.m_handle );
}
template < class T, bool B >
CDmeHandle( const CDmeHandle< T, B > &handle ) : m_handle( DMELEMENT_HANDLE_INVALID )
{
DmeType *p = ( T* )NULL; // triggers compiler error if converting from invalid handle type
NOTE_UNUSED( p );
Set( handle.GetHandle() );
}
~CDmeHandle()
{
if ( !g_pDataModel )
return; // some handles are static, and don't get destroyed until program termination
Unref( m_handle, Counted );
}
template < class T, bool B >
CDmeHandle& operator=( const CDmeHandle< T, B > &handle )
{
DmeType *p = ( T* )NULL; // triggers compiler error if converting from invalid handle type
NOTE_UNUSED( p );
Set( handle.GetHandle() );
return *this;
}
DmeType *Get()
{
return static_cast< DmeType* >( g_pDataModel->GetElement( m_handle ) );
}
const DmeType *Get() const
{
return static_cast< DmeType* >( g_pDataModel->GetElement( m_handle ) );
}
DmElementHandle_t GetHandle() const
{
return m_handle;
}
void Set( CDmElement *pObject )
{
Set( pObject ? pObject->GetHandle() : DMELEMENT_HANDLE_INVALID );
}
void Set( DmElementHandle_t h )
{
if ( h == m_handle )
return;
Unref( m_handle, Counted );
m_handle = h;
if ( h != DMELEMENT_HANDLE_INVALID )
{
CDmElement *pElement = g_pDataModel->GetElement( m_handle );
Assert( pElement );
if ( pElement && !pElement->IsA( DmeType::GetStaticTypeSymbol() ) )
{
m_handle = DMELEMENT_HANDLE_INVALID;
}
}
Ref( m_handle, Counted );
}
operator DmeType*()
{
return Get();
}
operator const DmeType*() const
{
return Get();
}
operator DmElementHandle_t() const
{
return m_handle;
}
DmeType* operator->()
{
return Get();
}
const DmeType* operator->() const
{
return Get();
}
CDmeHandle& operator=( DmElementHandle_t h )
{
Set( h );
return *this;
}
CDmeHandle& operator=( CDmElement *pObject )
{
Set( pObject );
return *this;
}
bool operator==( const CDmeHandle< DmeType > &h ) const
{
return m_handle == h.m_handle;
}
bool operator!=( const CDmeHandle< DmeType > &h ) const
{
return !operator==( h );
}
bool operator<( const CDmeHandle< DmeType > &h ) const
{
return m_handle < h.m_handle;
}
bool operator==( DmeType *pObject ) const
{
DmElementHandle_t h = pObject ? pObject->GetHandle() : DMELEMENT_HANDLE_INVALID;
return m_handle == h;
}
bool operator!=( DmeType *pObject ) const
{
return !operator==( pObject );
}
bool operator==( DmElementHandle_t h ) const
{
return ( m_handle == h );
}
bool operator!=( DmElementHandle_t h ) const
{
return ( m_handle != h );
}
operator bool() const
{
return ( Get() != NULL );
}
bool operator!() const
{
return ( Get() == NULL );
}
private:
DmElementHandle_t m_handle;
};
typedef CDmeHandle< CDmElement, true > CDmeCountedHandle;
//-----------------------------------------------------------------------------
// Vector of element handles
//-----------------------------------------------------------------------------
typedef CUtlVector< CDmeHandle<CDmElement> > DmeHandleVec_t;
//-----------------------------------------------------------------------------
// helper class for undo classes to allow them to hold onto refcounted element handles
//-----------------------------------------------------------------------------
template< typename T >
class CDmAttributeUndoStorageType
{
public:
typedef T UndoStorageType;
};
template<>
class CDmAttributeUndoStorageType< DmElementHandle_t >
{
public:
typedef CDmeCountedHandle UndoStorageType;
};
template<>
class CDmAttributeUndoStorageType< CUtlVector< DmElementHandle_t > >
{
public:
typedef CUtlVector< CDmeCountedHandle > UndoStorageType;
};
#endif // DMEHANDLE_H

View File

@ -0,0 +1,618 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef DMELEMENT_H
#define DMELEMENT_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utlmap.h"
#include "tier1/utlhash.h"
#include "tier1/utlvector.h"
#include "tier1/utlsymbol.h"
#include "datamodel/attributeflags.h"
#include "datamodel/idatamodel.h"
#include "datamodel/dmvar.h"
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
typedef bool (CDmElement::*pfnCommandMethod)( const char *command, const char *args );
// element/element array traversal path item - assumes the full path does NOT contain cycles
struct ElementPathItem_t
{
ElementPathItem_t( DmElementHandle_t hElem = DMELEMENT_HANDLE_INVALID,
DmAttributeHandle_t hAttr = DMATTRIBUTE_HANDLE_INVALID,
int idx = -1 )
: hElement( hElem ), hAttribute( hAttr ), nIndex( idx )
{
}
// only uses hElement so that it can be used to search for elements
bool operator==( const ElementPathItem_t &that ) const
{
return hElement == that.hElement;
}
DmElementHandle_t hElement;
DmAttributeHandle_t hAttribute;
int nIndex;
};
//-----------------------------------------------------------------------------
// singly-linked attribute list
//-----------------------------------------------------------------------------
struct DmAttributeList_t
{
DmAttributeList_t() : m_hAttribute( DMATTRIBUTE_HANDLE_INVALID ), m_pNext( NULL ) {}
DmAttributeHandle_t m_hAttribute;
DmAttributeList_t *m_pNext;
};
//-----------------------------------------------------------------------------
// helper class to allow CDmeHandle access to g_pDataModelImp
//-----------------------------------------------------------------------------
class CDmeElementRefHelper
{
protected:
void Ref ( DmElementHandle_t hElement, bool bStrong );
void Unref( DmElementHandle_t hElement, bool bStrong );
};
//-----------------------------------------------------------------------------
// element reference struct - containing attribute referrers and handle refcount
//-----------------------------------------------------------------------------
struct DmElementReference_t
{
explicit DmElementReference_t( DmElementHandle_t hElement = DMELEMENT_HANDLE_INVALID ) :
m_hElement( hElement ), m_nWeakHandleCount( 0 ), m_nStrongHandleCount( 0 )
{
}
DmElementReference_t( const DmElementReference_t &that ) :
m_hElement( that.m_hElement ), m_nWeakHandleCount( that.m_nWeakHandleCount ),
m_nStrongHandleCount( that.m_nStrongHandleCount ), m_attributes( that.m_attributes )
{
}
DmElementReference_t &operator=( const DmElementReference_t &that )
{
m_hElement = that.m_hElement;
m_nWeakHandleCount = that.m_nWeakHandleCount;
m_nStrongHandleCount = that.m_nStrongHandleCount;
m_attributes.m_hAttribute = that.m_attributes.m_hAttribute;
m_attributes.m_pNext = that.m_attributes.m_pNext;
return *this;
}
~DmElementReference_t()
{
// Assert( !IsStronglyReferenced() );
}
void AddAttribute( CDmAttribute *pAttribute );
void RemoveAttribute( CDmAttribute *pAttribute );
bool IsStronglyReferenced() // should this element be kept around (even if it's DmElementHandle_t is invalidated)
{
return m_attributes.m_hAttribute != DMATTRIBUTE_HANDLE_INVALID || m_nStrongHandleCount > 0;
}
bool IsWeaklyReferenced() // should we keep this element's DmElementHandle_t mapped to it's id (even if the element is deleted)
{
return IsStronglyReferenced() || m_nWeakHandleCount > 0;
}
int EstimateMemoryOverhead()
{
int nBytes = 0;
for ( DmAttributeList_t *pLink = m_attributes.m_pNext; pLink; pLink = pLink->m_pNext )
{
nBytes += sizeof( DmAttributeList_t );
}
return nBytes;
}
DmElementHandle_t m_hElement;
unsigned short m_nWeakHandleCount; // CDmeHandle<T> - for auto-hookup once the element comes back, mainly used by UI
unsigned short m_nStrongHandleCount; // CDmeCountedElementRef - for preventing elements from being truly deleted, mainly used by undo and file root
DmAttributeList_t m_attributes;
};
//-----------------------------------------------------------------------------
// Base DmElement we inherit from in higher-level classes
//-----------------------------------------------------------------------------
class CDmElement
{
public:
// Can be overridden by derived classes
virtual void OnAttributeChanged( CDmAttribute *pAttribute ) {}
virtual void PreAttributeChanged( CDmAttribute *pAttribute ) {}
virtual void OnAttributeArrayElementAdded( CDmAttribute *pAttribute, int nFirstElem, int nLastElem ) {}
virtual void OnAttributeArrayElementRemoved( CDmAttribute *pAttribute, int nFirstElem, int nLastElem ) {}
virtual void Resolve() {}
virtual bool IsA( UtlSymId_t typeSymbol ) const;
virtual int GetInheritanceDepth( UtlSymId_t typeSymbol ) const;
virtual void OnElementUnserialized() {}
virtual int AllocatedSize() const { return sizeof( CDmElement ); }
// Returns the element handle
DmElementHandle_t GetHandle() const;
// Attribute iteration, finding
// NOTE: Passing a type into GetAttribute will return NULL if the attribute exists but isn't that type
bool HasAttribute( const char *pAttributeName, DmAttributeType_t type = AT_UNKNOWN ) const;
CDmAttribute *GetAttribute( const char *pAttributeName, DmAttributeType_t type = AT_UNKNOWN );
const CDmAttribute *GetAttribute( const char *pAttributeName, DmAttributeType_t type = AT_UNKNOWN ) const;
int AttributeCount() const;
CDmAttribute* FirstAttribute();
const CDmAttribute* FirstAttribute() const;
// Element name, type, ID
// WARNING: SetType() should only be used by format conversion methods (dmxconvert)
UtlSymId_t GetType() const;
const char * GetTypeString() const;
const char * GetName() const;
const DmObjectId_t& GetId() const;
void SetType( const char *pType );
void SetName( const char* pName );
// Attribute management
CDmAttribute * AddAttribute( const char *pAttributeName, DmAttributeType_t type );
template< class E > CDmAttribute* AddAttributeElement( const char *pAttributeName );
template< class E > CDmAttribute* AddAttributeElementArray( const char *pAttributeName );
void RemoveAttribute( const char *pAttributeName );
void RemoveAttributeByPtr( CDmAttribute *pAttributeName );
void RenameAttribute( const char *pAttributeName, const char *pNewName );
// get attribute value
template< class T > const T& GetValue( const char *pAttributeName ) const;
template< class T > const T& GetValue( const char *pAttributeName, const T& defaultValue ) const;
const char * GetValueString( const char *pAttributeName ) const;
template< class E > E* GetValueElement( const char *pAttributeName ) const;
// set attribute value
CDmAttribute* SetValue( const char *pAttributeName, const void *value, size_t size );
template< class T > CDmAttribute* SetValue( const char *pAttributeName, const T& value );
template< class E > CDmAttribute* SetValue( const char *pAttributeName, E* value );
// set attribute value if the attribute doesn't already exist
CDmAttribute* InitValue( const char *pAttributeName, const void *value, size_t size );
template< class T > CDmAttribute* InitValue( const char *pAttributeName, const T& value );
template< class E > CDmAttribute* InitValue( const char *pAttributeName, E* value );
// Parses an attribute from a string
// Doesn't create an attribute if it doesn't exist and always preserves attribute type
void SetValueFromString( const char *pAttributeName, const char *value );
const char *GetValueAsString( const char *pAttributeName, char *pBuffer, size_t buflen ) const;
// Helpers for our RTTI
template< class E > bool IsA() const;
bool IsA( const char *pTypeName ) const;
int GetInheritanceDepth( const char *pTypeName ) const;
static CUtlSymbol GetStaticTypeSymbol();
// Indicates whether this element should be copied or not
void SetShared( bool bShared );
bool IsShared() const;
// Copies an element and all its attributes
CDmElement* Copy( TraversalDepth_t depth = TD_DEEP ) const;
// Copies attributes from a specified element
void CopyAttributesTo( CDmElement *pCopy, TraversalDepth_t depth = TD_DEEP ) const;
// recursively set fileid's, with option to only change elements in the matched file
void SetFileId( DmFileId_t fileid, TraversalDepth_t depth, bool bOnlyIfMatch = false );
DmFileId_t GetFileId() const;
bool IsAccessible() const;
void MarkAccessible( bool bAccessible );
void MarkAccessible( TraversalDepth_t depth = TD_ALL );
// returns the first path to the element found traversing all element/element
// array attributes - not necessarily the shortest.
// cycle-safe (skips any references to elements in the current path)
// but may re-traverse elements via different paths
bool FindElement( const CDmElement *pElement, CUtlVector< ElementPathItem_t > &elementPath, TraversalDepth_t depth ) const;
bool FindReferer( DmElementHandle_t hElement, CUtlVector< ElementPathItem_t > &elementPath, TraversalDepth_t depth ) const;
void RemoveAllReferencesToElement( CDmElement *pElement );
bool IsStronglyReferenced() { return m_ref.IsStronglyReferenced(); }
// Estimates the memory usage of the element, its attributes, and child elements
int EstimateMemoryUsage( TraversalDepth_t depth = TD_DEEP );
protected:
// NOTE: These are protected to ensure that the factory is the only thing that can create these
CDmElement( DmElementHandle_t handle, const char *objectType, const DmObjectId_t &id, const char *objectName, DmFileId_t fileid );
virtual ~CDmElement();
// Used by derived classes to do construction and setting up CDmaVars
void OnConstruction() { }
void OnDestruction() { }
virtual void PerformConstruction();
virtual void PerformDestruction();
// Internal methods related to RTII
static void SetTypeSymbol( CUtlSymbol sym );
static bool IsA_Implementation( CUtlSymbol typeSymbol );
static int GetInheritanceDepth_Implementation( CUtlSymbol typeSymbol, int nCurrentDepth );
// Internal method for creating a copy of this element
CDmElement* CopyInternal( TraversalDepth_t depth = TD_DEEP ) const;
// helper for making attributevarelementarray cleanup easier
template< class T > static void DeleteAttributeVarElementArray( T &array );
private:
typedef CUtlMap< DmElementHandle_t, DmElementHandle_t, int > CRefMap;
// Bogus constructor
CDmElement();
// internal recursive copy method - builds refmap of old element's handle -> copy's handle, and uses it to fixup references
void CopyAttributesTo( CDmElement *pCopy, CRefMap &refmap, TraversalDepth_t depth ) const;
void CopyElementAttribute( const CDmAttribute *pAttr, CDmAttribute *pCopyAttr, CRefMap &refmap, TraversalDepth_t depth ) const;
void CopyElementArrayAttribute( const CDmAttribute *pAttr, CDmAttribute *pCopyAttr, CRefMap &refmap, TraversalDepth_t depth ) const;
void FixupReferences( CUtlHashFast< DmElementHandle_t > &visited, const CRefMap &refmap, TraversalDepth_t depth );
void SetFileId( DmFileId_t fileid );
void SetFileId_R( CUtlHashFast< DmElementHandle_t > &visited, DmFileId_t fileid, TraversalDepth_t depth, DmFileId_t match, bool bOnlyIfMatch );
CDmAttribute* CreateAttribute( const char *pAttributeName, DmAttributeType_t type );
void RemoveAttribute( CDmAttribute **pAttrRef );
CDmAttribute* AddExternalAttribute( const char *pAttributeName, DmAttributeType_t type, void *pMemory );
CDmAttribute *FindAttribute( const char *pAttributeName ) const;
void Purge();
void SetId( const DmObjectId_t &id );
bool IsDirty() const;
void MarkDirty( bool dirty = true );
void MarkAttributesClean();
void MarkBeingUnserialized( bool beingUnserialized = true );
bool IsBeingUnserialized() const;
// Used by the undo system only.
void AddAttributeByPtr( CDmAttribute *ptr );
void RemoveAttributeByPtrNoDelete( CDmAttribute *ptr );
// Should only be called from datamodel, who will take care of changing the fileset entry as well
void ChangeHandle( DmElementHandle_t handle );
// returns element reference struct w/ list of referrers and handle count
DmElementReference_t* GetReference();
void SetReference( const DmElementReference_t &ref );
// Estimates memory usage
int EstimateMemoryUsage( CUtlHash< DmElementHandle_t > &visited, TraversalDepth_t depth, int *pCategories );
protected:
CDmaString m_Name;
private:
CDmAttribute *m_pAttributes;
DmElementReference_t m_ref;
UtlSymId_t m_Type;
bool m_bDirty : 1;
bool m_bBeingUnserialized : 1;
bool m_bIsAcessible : 1;
unsigned char m_nReserved; // Makes Id be quad aligned
DmObjectId_t m_Id;
DmFileId_t m_fileId;
// Stores the type symbol
static CUtlSymbol m_classType;
// Factories can access our constructors
template <class T> friend class CDmElementFactory;
template <class T> friend class CDmAbstractElementFactory;
template< class T > friend class CDmaVar;
template< class T > friend class CDmaArray;
template< class T > friend class CDmaElementArray;
template< class T, class B > friend class CDmaDecorator;
template< class T > friend class CDmrElementArray;
friend class CDmElementFactoryDefault;
friend class CDmeElementAccessor;
friend class CDmeOperator;
friend void CopyElements( const CUtlVector< CDmElement* > &from, CUtlVector< CDmElement* > &to, TraversalDepth_t depth );
};
inline void DestroyElement( CDmElement *pElement )
{
if ( pElement )
{
g_pDataModel->DestroyElement( pElement->GetHandle() );
}
}
void DestroyElement( CDmElement *pElement, TraversalDepth_t depth );
//-----------------------------------------------------------------------------
// copy groups of elements together so that references between them are maintained
//-----------------------------------------------------------------------------
void CopyElements( const CUtlVector< CDmElement* > &from, CUtlVector< CDmElement* > &to, TraversalDepth_t depth = TD_DEEP );
//-----------------------------------------------------------------------------
// allows elements to chain OnAttributeChanged up to their parents (or at least, referrers)
//-----------------------------------------------------------------------------
void InvokeOnAttributeChangedOnReferrers( DmElementHandle_t hElement, CDmAttribute *pChangedAttr );
//-----------------------------------------------------------------------------
// Returns the type, name, id, fileId
//-----------------------------------------------------------------------------
inline UtlSymId_t CDmElement::GetType() const
{
return m_Type;
}
inline const char *CDmElement::GetTypeString() const
{
return g_pDataModel->GetString( m_Type );
}
inline const char *CDmElement::GetName() const
{
return m_Name.Get();
}
inline void CDmElement::SetName( const char* pName )
{
m_Name.Set( pName );
}
inline const DmObjectId_t& CDmElement::GetId() const
{
return m_Id;
}
inline DmFileId_t CDmElement::GetFileId() const
{
return m_fileId;
}
//-----------------------------------------------------------------------------
// Controls whether the element should be copied by default
//-----------------------------------------------------------------------------
inline void CDmElement::SetShared( bool bShared )
{
if ( bShared )
{
SetValue< bool >( "shared", true );
}
else
{
RemoveAttribute( "shared" );
}
}
inline bool CDmElement::IsShared() const
{
return GetValue< bool >( "shared" ); // if attribute doesn't exist, returns default bool value, which is false
}
//-----------------------------------------------------------------------------
// Copies attributes from a specified element
//-----------------------------------------------------------------------------
inline CDmElement* CDmElement::Copy( TraversalDepth_t depth ) const
{
return CopyInternal( depth );
}
//-----------------------------------------------------------------------------
// RTTI
//-----------------------------------------------------------------------------
inline bool CDmElement::IsA_Implementation( CUtlSymbol typeSymbol )
{
return ( m_classType == typeSymbol ) || ( UTL_INVAL_SYMBOL == typeSymbol );
}
inline int CDmElement::GetInheritanceDepth_Implementation( CUtlSymbol typeSymbol, int nCurrentDepth )
{
return IsA_Implementation( typeSymbol ) ? nCurrentDepth : -1;
}
inline CUtlSymbol CDmElement::GetStaticTypeSymbol()
{
return m_classType;
}
inline bool CDmElement::IsA( const char *pTypeName ) const
{
CUtlSymbol typeSymbol = g_pDataModel->GetSymbol( pTypeName );
return IsA( typeSymbol );
}
template< class E > inline bool CDmElement::IsA() const
{
return IsA( E::GetStaticTypeSymbol() );
}
//-----------------------------------------------------------------------------
// Helper for finding elements that refer to this element
//-----------------------------------------------------------------------------
template< class T >
T *FindReferringElement( CDmElement *pElement, const char *pAttrName, bool bMustBeInSameFile = true )
{
return FindReferringElement< T >( pElement, g_pDataModel->GetSymbol( pAttrName ), bMustBeInSameFile );
}
void RemoveElementFromRefereringAttributes( CDmElement *pElement, bool bPreserveOrder = true );
//-----------------------------------------------------------------------------
//
// element-specific unique name generation methods
//
//-----------------------------------------------------------------------------
// returns startindex if none found, 2 if only "prefix" found, and n+1 if "prefixn" found
int GenerateUniqueNameIndex( const char *prefix, const CUtlVector< DmElementHandle_t > &array, int startindex = -1 );
bool GenerateUniqueName( char *name, int memsize, const char *prefix, const CUtlVector< DmElementHandle_t > &array );
void MakeElementNameUnique( CDmElement *pElement, const char *prefix, const CUtlVector< DmElementHandle_t > &array, bool forceIndex = false );
//-----------------------------------------------------------------------------
// helper for making attributevarelementarray cleanup easier
//-----------------------------------------------------------------------------
template< class T >
inline void CDmElement::DeleteAttributeVarElementArray( T &array )
{
int nElements = array.Count();
for ( int i = 0; i < nElements; ++i )
{
g_pDataModel->DestroyElement( array.GetHandle( i ) );
}
array.RemoveAll();
}
//-----------------------------------------------------------------------------
// Default size computation
//-----------------------------------------------------------------------------
template< class T >
int DmeEstimateMemorySize( T* pElement )
{
return sizeof( T );
}
//-----------------------------------------------------------------------------
// Helper macro to create an element; this is used for elements that are helper base classes
//-----------------------------------------------------------------------------
#define DEFINE_UNINSTANCEABLE_ELEMENT( className, baseClassName ) \
protected: \
className( DmElementHandle_t handle, const char *pElementTypeName, const DmObjectId_t &id, const char *pElementName, DmFileId_t fileid ) : \
baseClassName( handle, pElementTypeName, id, pElementName, fileid ) \
{ \
} \
virtual ~className() \
{ \
} \
void OnConstruction(); \
void OnDestruction(); \
virtual void PerformConstruction() \
{ \
BaseClass::PerformConstruction(); \
OnConstruction(); \
} \
virtual void PerformDestruction() \
{ \
OnDestruction(); \
BaseClass::PerformDestruction(); \
} \
virtual int AllocatedSize() const { return DmeEstimateMemorySize( this ); } \
\
private: \
typedef baseClassName BaseClass; \
//-----------------------------------------------------------------------------
// Helper macro to create the class factory
//-----------------------------------------------------------------------------
#define DEFINE_ELEMENT( className, baseClassName ) \
public: \
virtual bool IsA( UtlSymId_t typeSymbol ) const \
{ \
return IsA_Implementation( typeSymbol );\
} \
\
bool IsA( const char *pTypeName ) const \
{ \
CUtlSymbol typeSymbol = g_pDataModel->GetSymbol( pTypeName ); \
return IsA( typeSymbol ); \
} \
\
template< class T > bool IsA() const \
{ \
return IsA( T::GetStaticTypeSymbol() ); \
} \
\
virtual int GetInheritanceDepth( UtlSymId_t typeSymbol ) const \
{ \
return GetInheritanceDepth_Implementation( typeSymbol, 0 ); \
} \
\
static CUtlSymbol GetStaticTypeSymbol( ) \
{ \
return m_classType; \
} \
\
className* Copy( TraversalDepth_t depth = TD_DEEP ) const \
{ \
return static_cast< className* >( CopyInternal( depth ) ); \
} \
protected: \
className( DmElementHandle_t handle, const char *pElementTypeName, const DmObjectId_t &id, const char *pElementName, DmFileId_t fileid ) : \
baseClassName( handle, pElementTypeName, id, pElementName, fileid ) \
{ \
} \
virtual ~className() \
{ \
} \
void OnConstruction(); \
void OnDestruction(); \
virtual void PerformConstruction() \
{ \
BaseClass::PerformConstruction(); \
OnConstruction(); \
} \
virtual void PerformDestruction() \
{ \
OnDestruction(); \
BaseClass::PerformDestruction(); \
} \
static void SetTypeSymbol( CUtlSymbol typeSymbol ) \
{ \
m_classType = typeSymbol; \
} \
\
static bool IsA_Implementation( CUtlSymbol typeSymbol ) \
{ \
if ( typeSymbol == m_classType ) \
return true; \
return BaseClass::IsA_Implementation( typeSymbol ); \
} \
\
static int GetInheritanceDepth_Implementation( CUtlSymbol typeSymbol, int nCurrentDepth ) \
{ \
if ( typeSymbol == m_classType ) \
return nCurrentDepth; \
return BaseClass::GetInheritanceDepth_Implementation( typeSymbol, nCurrentDepth+1 );\
} \
virtual int AllocatedSize() const { return DmeEstimateMemorySize( this ); } \
\
private: \
typedef baseClassName BaseClass; \
template <class T> friend class CDmElementFactory; \
template <class T> friend class CDmAbstractElementFactory; \
static CUtlSymbol m_classType
#define IMPLEMENT_ELEMENT( className ) \
CUtlSymbol className::m_classType = UTL_INVAL_SYMBOL;
#endif // DMELEMENT_H

View File

@ -0,0 +1,190 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef DMELEMENTFACTORYHELPER_H
#define DMELEMENTFACTORYHELPER_H
#ifdef _WIN32
#pragma once
#endif
#include "datamodel/idatamodel.h"
#include "datamodel/dmelement.h"
#include "datamodel/dmattribute.h"
#include "datamodel/dmattributevar.h"
#include "tier1/utlvector.h"
#include "tier1/utlsymbol.h"
//-----------------------------------------------------------------------------
// Internal interface for IDmElementFactory
//-----------------------------------------------------------------------------
class IDmElementFactoryInternal : public IDmElementFactory
{
public:
virtual void SetElementTypeSymbol( CUtlSymbol sym ) = 0;
virtual bool IsAbstract() const = 0;
};
//-----------------------------------------------------------------------------
// Class used to register factories into a global list
//-----------------------------------------------------------------------------
class CDmElementFactoryHelper
{
public:
// Static list of helpers
static CDmElementFactoryHelper *s_pHelpers[2];
// Create all the hud elements
static void InstallFactories( );
public:
// Construction
CDmElementFactoryHelper( const char *pClassName, IDmElementFactoryInternal *pFactory, bool bIsStandardFactory );
// Accessors
CDmElementFactoryHelper *GetNext( void );
const char *GetClassname();
IDmElementFactoryInternal *GetFactory();
private:
// Next factory in list
CDmElementFactoryHelper *m_pNext;
// Creation function to use for this technology
IDmElementFactoryInternal *m_pFactory;
const char *m_pszClassname;
};
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline const char *CDmElementFactoryHelper::GetClassname()
{
return m_pszClassname;
}
inline IDmElementFactoryInternal *CDmElementFactoryHelper::GetFactory()
{
return m_pFactory;
}
//-----------------------------------------------------------------------------
// Helper Template factory for simple creation of factories
//-----------------------------------------------------------------------------
template <class T >
class CDmElementFactory : public IDmElementFactoryInternal
{
public:
CDmElementFactory( const char *pLookupName ) : m_pLookupName( pLookupName ) {}
// Creation, destruction
virtual CDmElement* Create( DmElementHandle_t handle, const char *pElementType, const char *pElementName, DmFileId_t fileid, const DmObjectId_t &id )
{
return new T( handle, m_pLookupName, id, pElementName, fileid );
}
virtual void Destroy( DmElementHandle_t hElement )
{
CDmElement *pElement = g_pDataModel->GetElement( hElement );
if ( pElement )
{
T *pActualElement = static_cast< T* >( pElement );
delete pActualElement;
}
}
// Sets the type symbol, used for "isa" implementation
virtual void SetElementTypeSymbol( CUtlSymbol sym )
{
T::SetTypeSymbol( sym );
}
virtual bool IsAbstract() const { return false; }
private:
const char *m_pLookupName;
};
template < class T >
class CDmAbstractElementFactory : public IDmElementFactoryInternal
{
public:
CDmAbstractElementFactory() {}
// Creation, destruction
virtual CDmElement* Create( DmElementHandle_t handle, const char *pElementType, const char *pElementName, DmFileId_t fileid, const DmObjectId_t &id )
{
return NULL;
}
virtual void Destroy( DmElementHandle_t hElement )
{
}
// Sets the type symbol, used for "isa" implementation
virtual void SetElementTypeSymbol( CUtlSymbol sym )
{
T::SetTypeSymbol( sym );
}
virtual bool IsAbstract() const { return true; }
private:
};
//-----------------------------------------------------------------------------
// Helper macro to create the class factory
//-----------------------------------------------------------------------------
#if defined( MOVIEOBJECTS_LIB ) || defined ( DATAMODEL_LIB ) || defined ( DMECONTROLS_LIB )
#define IMPLEMENT_ELEMENT_FACTORY( lookupName, className ) \
IMPLEMENT_ELEMENT( className ) \
CDmElementFactory< className > g_##className##_Factory( #lookupName ); \
CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, true ); \
className *g_##className##LinkerHack = NULL;
#define IMPLEMENT_ABSTRACT_ELEMENT( lookupName, className ) \
IMPLEMENT_ELEMENT( className ) \
CDmAbstractElementFactory< className > g_##className##_Factory; \
CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, true ); \
className *g_##className##LinkerHack = NULL;
#else
#define IMPLEMENT_ELEMENT_FACTORY( lookupName, className ) \
IMPLEMENT_ELEMENT( className ) \
CDmElementFactory< className > g_##className##_Factory( #lookupName ); \
CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, false ); \
className *g_##className##LinkerHack = NULL;
#define IMPLEMENT_ABSTRACT_ELEMENT( lookupName, className ) \
IMPLEMENT_ELEMENT( className ) \
CDmAbstractElementFactory< className > g_##className##_Factory; \
CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, false ); \
className *g_##className##LinkerHack = NULL;
#endif
// Used by classes defined in movieobjects or scenedatabase that must be explicitly installed
#define IMPLEMENT_ELEMENT_FACTORY_INSTALL_EXPLICITLY( lookupName, className ) \
IMPLEMENT_ELEMENT( className ) \
CDmElementFactory< className > g_##className##_Factory( #lookupName ); \
CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, false ); \
className *g_##className##LinkerHack = NULL;
//-----------------------------------------------------------------------------
// Installs dm element factories
//-----------------------------------------------------------------------------
void InstallDmElementFactories( );
#endif // DMELEMENTFACTORYHELPER_H

View File

@ -0,0 +1,47 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef DMELEMENTHANDLE_H
#define DMELEMENTHANDLE_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// handle to an CDmElement
//-----------------------------------------------------------------------------
#define PERFORM_HANDLE_TYPECHECKING 0
#if PERFORM_HANDLE_TYPECHECKING
// this is here to make sure we're being type-safe about element handles
// otherwise, the compiler lets us cast to bool incorrectly
// the other solution would be to redefine DmElementHandle_t s.t. DMELEMENT_HANDLE_INVALID==0
struct DmElementHandle_t
{
DmElementHandle_t() : handle( 0xffffffff ) {}
explicit DmElementHandle_t( int h ) : handle( h ) {}
inline bool operator==( const DmElementHandle_t &h ) const { return handle == h.handle; }
inline bool operator!=( const DmElementHandle_t &h ) const { return handle != h.handle; }
inline bool operator<( const DmElementHandle_t &h ) const { return handle < h.handle; }
// inline operator int() const { return handle; } // if we're okay with implicit int casts, uncomment this method
int handle;
};
const DmElementHandle_t DMELEMENT_HANDLE_INVALID;
#else // PERFORM_HANDLE_TYPECHECKING
enum DmElementHandle_t
{
DMELEMENT_HANDLE_INVALID = 0xffffffff
};
#endif // PERFORM_HANDLE_TYPECHECKING
#endif // DMELEMENTHANDLE_H

93
public/datamodel/dmvar.h Normal file
View File

@ -0,0 +1,93 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef DMVAR_H
#define DMVAR_H
#ifdef _WIN32
#pragma once
#endif
class CDmAttribute;
//-----------------------------------------------------------------------------
// Helper template for external attributes
//-----------------------------------------------------------------------------
template< typename T >
class CDmaVar
{
typedef typename CDmAttributeInfo< T >::StorageType_t D;
public:
CDmaVar( );
// Setup to be used in OnConstruction methods of DmElements
void Init( CDmElement *pOwner, const char *pAttributeName, int flags = 0 );
void InitAndSet( CDmElement *pOwner, const char *pAttributeName, const T &value, int flags = 0 );
// Set/get
const T& Set( const T &val );
const T& Get() const;
// Cast operators
operator const T&() const;
const T* operator->() const;
// Assignment operator
const CDmaVar<T>& operator=( const CDmaVar<T>& src );
// Math utility operations
const T& operator=( const T &val );
const T& operator+=( const T &val );
const T& operator-=( const T &val );
const T& operator/=( const T &val );
const T& operator*=( const T &val );
const T& operator^=( const T &val );
const T& operator|=( const T &val );
const T& operator&=( const T &val );
T operator++();
T operator--();
T operator++( int ); // postfix version..
T operator--( int ); // postfix version..
// Returns the attribute associated with the var
CDmAttribute *GetAttribute();
const CDmAttribute *GetAttribute() const;
// Is the attribute dirty?
bool IsDirty() const;
protected:
const T& Value() const;
T& Value();
const D& Storage() const;
D& Storage();
private:
D m_Storage;
protected:
CDmAttribute *m_pAttribute;
};
//-----------------------------------------------------------------------------
// Specialization for string
//-----------------------------------------------------------------------------
class CDmaString : public CDmaVar< CUtlString >
{
public:
const char *Get( ) const;
operator const char*() const;
void Set( const char *pValue );
CDmaString &operator=( const char *src );
const CDmaString& operator=( const CDmaString& src );
// Returns strlen
int Length() const;
};
#endif // DMVAR_H

View File

@ -0,0 +1,938 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef IDATAMODEL_H
#define IDATAMODEL_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/interface.h"
#include "tier1/utlvector.h"
#include "tier1/utlsymbol.h"
#include "appframework/IAppSystem.h"
#include "datamodel/dmattributetypes.h"
//-----------------------------------------------------------------------------
// Forward declarations:
//-----------------------------------------------------------------------------
class CDmAttribute;
class CDmElement;
class IDmeOperator;
class IElementForKeyValueCallback;
struct DmValueBase_t;
class CUtlBuffer;
class KeyValues;
class CUtlSymbolTable;
class CUtlCharConversion;
//-----------------------------------------------------------------------------
// data file format info
//-----------------------------------------------------------------------------
#define DMX_LEGACY_VERSION_STARTING_TOKEN "<!-- DMXVersion"
#define DMX_LEGACY_VERSION_ENDING_TOKEN "-->"
#define DMX_VERSION_STARTING_TOKEN "<!-- dmx"
#define DMX_VERSION_ENDING_TOKEN "-->"
#define GENERIC_DMX_FORMAT "dmx"
enum
{
DMX_MAX_FORMAT_NAME_MAX_LENGTH = 64,
DMX_MAX_HEADER_LENGTH = 40 + 2 * DMX_MAX_FORMAT_NAME_MAX_LENGTH,
};
struct DmxHeader_t
{
char encodingName[ DMX_MAX_FORMAT_NAME_MAX_LENGTH ];
int nEncodingVersion;
char formatName[ DMX_MAX_FORMAT_NAME_MAX_LENGTH ];
int nFormatVersion;
DmxHeader_t() : nEncodingVersion( -1 ), nFormatVersion( -1 )
{
encodingName[ 0 ] = formatName[ 0 ] = '\0';
}
};
//-----------------------------------------------------------------------------
// element framework phases
//-----------------------------------------------------------------------------
enum DmPhase_t
{
PH_EDIT,
PH_EDIT_APPLY,
PH_EDIT_RESOLVE,
PH_DEPENDENCY,
PH_OPERATE,
PH_OPERATE_RESOLVE,
PH_OUTPUT,
};
//-----------------------------------------------------------------------------
// file id - also used to refer to elements that don't have file associations
//-----------------------------------------------------------------------------
enum DmFileId_t
{
DMFILEID_INVALID = 0xffffffff
};
//-----------------------------------------------------------------------------
// Handle to an CDmAttribute
//-----------------------------------------------------------------------------
enum DmAttributeHandle_t
{
DMATTRIBUTE_HANDLE_INVALID = 0xffffffff
};
//-----------------------------------------------------------------------------
// Handle to an DmAttributeList_t
//-----------------------------------------------------------------------------
enum DmAttributeReferenceIterator_t
{
DMATTRIBUTE_REFERENCE_ITERATOR_INVALID = 0
};
//-----------------------------------------------------------------------------
// element framework interface
//-----------------------------------------------------------------------------
abstract_class IDmElementFramework : public IAppSystem
{
public:
// Methods of IAppSystem
virtual bool Connect( CreateInterfaceFn factory ) = 0;
virtual void Disconnect() = 0;
virtual void *QueryInterface( const char *pInterfaceName ) = 0;
virtual InitReturnVal_t Init() = 0;
virtual void Shutdown() = 0;
virtual DmPhase_t GetPhase() = 0;
virtual void SetOperators( const CUtlVector< IDmeOperator* > &operators ) = 0;
virtual void BeginEdit() = 0; // ends in edit phase, forces apply/resolve if from edit phase
virtual void Operate( bool bResolve ) = 0; // ends in output phase
virtual void Resolve() = 0;
};
//-----------------------------------------------------------------------------
// Used only by aplpications to hook in the element framework
//-----------------------------------------------------------------------------
#define VDMELEMENTFRAMEWORK_VERSION "VDmElementFrameworkVersion001"
//-----------------------------------------------------------------------------
// Main interface
//-----------------------------------------------------------------------------
extern IDmElementFramework *g_pDmElementFramework;
//-----------------------------------------------------------------------------
// datamodel operator interface - for all elements that need to be sorted in the operator dependency graph
//-----------------------------------------------------------------------------
abstract_class IDmeOperator
{
public:
virtual bool IsDirty() = 0; // ie needs to operate
virtual void Operate() = 0;
virtual void GetInputAttributes ( CUtlVector< CDmAttribute * > &attrs ) = 0;
virtual void GetOutputAttributes( CUtlVector< CDmAttribute * > &attrs ) = 0;
};
//-----------------------------------------------------------------------------
// Class factory methods:
//-----------------------------------------------------------------------------
class IDmElementFactory
{
public:
// Creation, destruction
virtual CDmElement* Create( DmElementHandle_t handle, const char *pElementType, const char *pElementName, DmFileId_t fileid, const DmObjectId_t &id ) = 0;
virtual void Destroy( DmElementHandle_t hElement ) = 0;
};
//-----------------------------------------------------------------------------
// Various serialization methods can be installed into the data model factory
//-----------------------------------------------------------------------------
enum DmConflictResolution_t
{
CR_DELETE_NEW,
CR_DELETE_OLD,
CR_COPY_NEW,
CR_FORCE_COPY,
};
// convert files to elements and back
// current file encodings supported: binary, xml, xml_flat, keyvalues2, keyvalues2_flat, keyvalues (vmf/vmt/actbusy), text? (qc/obj)
class IDmSerializer
{
public:
virtual const char *GetName() const = 0;
virtual const char *GetDescription() const = 0;
virtual bool IsBinaryFormat() const = 0;
virtual bool StoresVersionInFile() const = 0;
virtual int GetCurrentVersion() const = 0;
// Write into the UtlBuffer, return true if successful
// if we decide to implement non-identity conversions between formats on write, then the source and dest format will need to be passed in here
virtual bool Serialize( CUtlBuffer &buf, CDmElement *pRoot ) = 0;
// Read from the UtlBuffer, return true if successful, and return the read-in root in ppRoot.
virtual bool Unserialize( CUtlBuffer &buf, const char *pEncodingName, int nEncodingVersion,
const char *pSourceFormatName, int nSourceFormatVersion,
DmFileId_t fileid, DmConflictResolution_t idConflictResolution, CDmElement **ppRoot ) = 0;
};
// convert legacy elements to non-legacy elements
// legacy formats include: sfm_vN, binary_vN, keyvalues2_v1, keyvalues2_flat_v1, xml, xml_flat
// where N is a version number (1..9 for sfm, 1..2 for binary)
class IDmLegacyUpdater
{
public:
virtual const char *GetName() const = 0;
virtual bool IsLatestVersion() const = 0;
// Updates ppRoot to first non-legacy generic dmx format, returns false if the conversion fails
virtual bool Update( CDmElement **ppRoot ) = 0;
};
// converts old elements to new elements
// current formats include: sfm session, animset presets, particle definitions, exported maya character, etc.
class IDmFormatUpdater
{
public:
virtual const char *GetName() const = 0;
virtual const char *GetDescription() const = 0;
virtual const char *GetExtension() const = 0;
virtual int GetCurrentVersion() const = 0;
virtual const char *GetDefaultEncoding() const = 0;
// Converts pSourceRoot from nSourceVersion to the current version, returns false if the conversion fails
virtual bool Update( CDmElement **pRoot, int nSourceVersion ) = 0;
};
//-----------------------------------------------------------------------------
// Interface for callbacks to supply element types for specific keys inside keyvalues files
//-----------------------------------------------------------------------------
class IElementForKeyValueCallback
{
public:
virtual const char *GetElementForKeyValue( const char *pszKeyName, int iNestingLevel ) = 0;
};
//-----------------------------------------------------------------------------
// Purpose: Optional helper passed in with clipboard data which is called when it's time to clean up the clipboard data in case the application
// had some dynamically allocated data attached to a KV SetPtr object...
//-----------------------------------------------------------------------------
abstract_class IClipboardCleanup
{
public:
virtual void ReleaseClipboardData( CUtlVector< KeyValues * >& list ) = 0;
};
//-----------------------------------------------------------------------------
// Purpose: Can be installed to be called back when data changes
//-----------------------------------------------------------------------------
enum DmNotifySource_t
{
// Sources
NOTIFY_SOURCE_APPLICATION = 0,
NOTIFY_SOURCE_UNDO,
NOTIFY_SOURCE_FIRST_DME_CONTROL_SOURCE = 4, // Sources from dme_controls starts here
NOTIFY_SOURCE_FIRST_APPLICATION_SOURCE = 8, // Sources from applications starts here
};
enum DmNotifyFlags_t
{
// Does this dirty the document?
NOTIFY_SOURCE_BITS = 8,
NOTIFY_SETDIRTYFLAG = (1<<NOTIFY_SOURCE_BITS),
// Type of change (note NOTIFY_CHANGE_TOPOLOGICAL/NOTIFY_CHANGE_ATTRIBUTE_VALUE/NOTIFY_CHANGE_ATTRIBUTE_ARRAY_SIZE
// are set by the Datamodel itself)
NOTIFY_CHANGE_TOPOLOGICAL = (1<<(NOTIFY_SOURCE_BITS+4)), // Element created, destroyed, element attribute or element array attribute value changed
NOTIFY_CHANGE_ATTRIBUTE_VALUE = (1<<(NOTIFY_SOURCE_BITS+5)), // Non-element attribute value changed
NOTIFY_CHANGE_ATTRIBUTE_ARRAY_SIZE = (1<<(NOTIFY_SOURCE_BITS+6)), // Non-element array attribute added or removed
NOTIFY_CHANGE_OTHER = (1<<(NOTIFY_SOURCE_BITS+7)), // Non attribute related change (a change in UI, for example)
NOTIFY_CHANGE_MASK = ( NOTIFY_CHANGE_TOPOLOGICAL | NOTIFY_CHANGE_ATTRIBUTE_VALUE | NOTIFY_CHANGE_ATTRIBUTE_ARRAY_SIZE | NOTIFY_CHANGE_OTHER ),
};
abstract_class IDmNotify
{
public:
// See DmNotifySource_t and DmNotifyFlags_t
virtual void NotifyDataChanged( const char *pReason, int nNotifySource, int nNotifyFlags ) = 0;
};
//-----------------------------------------------------------------------------
// Purpose: Helper for debugging undo system
//-----------------------------------------------------------------------------
struct UndoInfo_t
{
bool terminator;
const char *desc;
const char *undo;
const char *redo;
int numoperations;
};
//-----------------------------------------------------------------------------
// Interface for undo
//-----------------------------------------------------------------------------
abstract_class IUndoElement
{
public:
virtual void Undo() = 0;
virtual void Redo() = 0;
virtual const char *UndoDesc() const = 0;
virtual const char *RedoDesc() const = 0;
virtual const char *GetDesc() const = 0;
virtual void Release() = 0;
protected:
virtual bool IsEndOfStream() const = 0;
virtual void SetEndOfStream( bool end ) = 0;
virtual ~IUndoElement() { }
friend class CUndoManager;
};
//-----------------------------------------------------------------------------
// traversal depth for copy, search, and other element/attribute traversals
//-----------------------------------------------------------------------------
enum TraversalDepth_t
{
TD_ALL, // traverse all attributes
TD_DEEP, // traverse attributes with FATTRIB_NEVERCOPY clear
TD_SHALLOW, // traverse attributes with FATTRIB_MUSTCOPY set
TD_NONE, // don't traverse any attributes
};
//-----------------------------------------------------------------------------
// Main interface for creation of all IDmeElements:
//-----------------------------------------------------------------------------
class IDataModel : public IAppSystem
{
public:
// Installs factories used to instance elements
virtual void AddElementFactory( const char *pElementTypeName, IDmElementFactory *pFactory ) = 0;
// This factory will be used to instance all elements whose type name isn't found.
virtual void SetDefaultElementFactory( IDmElementFactory *pFactory ) = 0;
virtual int GetFirstFactory() const = 0;
virtual int GetNextFactory( int index ) const = 0;
virtual bool IsValidFactory( int index ) const = 0;
virtual const char *GetFactoryName( int index ) const = 0;
// create/destroy element methods - proxies to installed element factories
virtual DmElementHandle_t CreateElement( UtlSymId_t typeSymbol, const char *pElementName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL ) = 0;
virtual DmElementHandle_t CreateElement( const char *pTypeName, const char *pElementName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL ) = 0;
virtual void DestroyElement( DmElementHandle_t hElement ) = 0;
// element handle related methods
virtual CDmElement* GetElement ( DmElementHandle_t hElement ) const = 0;
virtual UtlSymId_t GetElementType ( DmElementHandle_t hElement ) const = 0;
virtual const char* GetElementName ( DmElementHandle_t hElement ) const = 0;
virtual const DmObjectId_t& GetElementId ( DmElementHandle_t hElement ) const = 0;
virtual const char* GetAttributeNameForType( DmAttributeType_t attType ) const = 0;
virtual DmAttributeType_t GetAttributeTypeForName( const char *name ) const = 0;
// Adds various serializers and updaters
virtual void AddSerializer( IDmSerializer *pSerializer ) = 0;
virtual void AddLegacyUpdater( IDmLegacyUpdater *pUpdater ) = 0;
virtual void AddFormatUpdater( IDmFormatUpdater *pUpdater ) = 0;
// file format methods
virtual const char* GetFormatExtension( const char *pFormatName ) = 0;
virtual const char* GetFormatDescription( const char *pFormatName ) = 0;
virtual int GetFormatCount() const = 0;
virtual const char * GetFormatName( int i ) const = 0;
virtual const char * GetDefaultEncoding( const char *pFormatName ) = 0;
// file encoding methods
virtual int GetEncodingCount() const = 0;
virtual const char * GetEncodingName( int i ) const = 0;
virtual bool IsEncodingBinary( const char *pEncodingName ) const = 0;
virtual bool DoesEncodingStoreVersionInFile( const char *pEncodingName ) const = 0;
// For serialization, set the delimiter rules
// These methods are meant to be used by importer/exporters
virtual void SetSerializationDelimiter( CUtlCharConversion *pConv ) = 0;
virtual void SetSerializationArrayDelimiter( const char *pDelimiter ) = 0;
// used to skip auto-creation of child elements during unserialization
virtual bool IsUnserializing() = 0;
// Serialization of a element tree into a utlbuffer
virtual bool Serialize( CUtlBuffer &outBuf, const char *pEncodingName, const char *pFormatName, DmElementHandle_t hRoot ) = 0;
// Unserializes, returns the root of the unserialized tree in hRoot
// The file name passed in is simply for error messages and fileid creation
virtual bool Unserialize( CUtlBuffer &inBuf, const char *pEncodingName, const char *pSourceFormatName, const char *pFormatHint,
const char *pFileName, DmConflictResolution_t idConflictResolution, DmElementHandle_t &hRoot ) = 0;
// converts from elements from old file formats to elements for the current file format
virtual bool UpdateUnserializedElements( const char *pSourceFormatName, int nSourceFormatVersion,
DmFileId_t fileid, DmConflictResolution_t idConflictResolution, CDmElement **ppRoot ) = 0;
// force creation of untyped elements, ignoring type
virtual void OnlyCreateUntypedElements( bool bEnable ) = 0;
// Finds a serializer by name
virtual IDmSerializer* FindSerializer( const char *pEncodingName ) const = 0;
virtual IDmLegacyUpdater* FindLegacyUpdater( const char *pLegacyFormatName ) const = 0;
virtual IDmFormatUpdater* FindFormatUpdater( const char *pFormatName ) const = 0;
// saves element tree to a file
virtual bool SaveToFile( const char *pFileName, const char *pPathID, const char *pEncodingName, const char *pFormatName, CDmElement *pRoot ) = 0;
// restores file into an element tree
// NOTE: Format name is only used here for those formats which don't store
// the format name in the file. Use NULL for those formats which store the
// format name in the file.
virtual DmFileId_t RestoreFromFile( const char *pFileName, const char *pPathID, const char *pFormatHint, CDmElement **ppRoot, DmConflictResolution_t idConflictResolution = CR_DELETE_NEW, DmxHeader_t *pHeaderOut = NULL ) = 0;
// Sets the name of the DME element to create in keyvalues serialization
virtual void SetKeyValuesElementCallback( IElementForKeyValueCallback *pCallbackInterface ) = 0;
virtual const char *GetKeyValuesElementName( const char *pszKeyName, int iNestingLevel ) = 0;
// Global symbol table for the datamodel system
virtual UtlSymId_t GetSymbol( const char *pString ) = 0;
virtual const char * GetString( UtlSymId_t sym ) const = 0;
// Returns the total number of elements allocated at the moment
virtual int GetMaxNumberOfElements() = 0;
virtual int GetElementsAllocatedSoFar() = 0;
virtual int GetAllocatedAttributeCount() = 0;
virtual int GetAllocatedElementCount() = 0;
virtual DmElementHandle_t FirstAllocatedElement() = 0;
virtual DmElementHandle_t NextAllocatedElement( DmElementHandle_t it ) = 0;
// estimate memory usage
virtual int EstimateMemoryUsage( DmElementHandle_t hElement, TraversalDepth_t depth ) = 0;
// Undo/Redo support
virtual void SetUndoEnabled( bool enable ) = 0;
virtual bool IsUndoEnabled() const = 0;
virtual bool UndoEnabledForElement( const CDmElement *pElement ) const = 0;
virtual bool IsDirty() const = 0;
virtual bool CanUndo() const = 0;
virtual bool CanRedo() const = 0;
// If chaining ID is != 0 and the next StartUndo uses the same ID, then the operations will be chained together into a single undo operation
virtual void StartUndo( char const *undodesc, char const *redodesc, int nChainingID = 0 ) = 0;
virtual void FinishUndo() = 0;
virtual void AbortUndoableOperation() = 0; // called instead of FinishUndo, essentially performs and Undo() and WipeRedo() if any undo items have been added to the stack
virtual void ClearRedo() = 0;
virtual const char *GetUndoDesc() = 0;
virtual const char *GetRedoDesc() = 0;
// From the UI, perform the Undo operation
virtual void Undo() = 0;
virtual void Redo() = 0;
virtual void TraceUndo( bool state ) = 0; // if true, undo records spew as they are added
// Wipes out all Undo data
virtual void ClearUndo() = 0;
virtual void GetUndoInfo( CUtlVector< UndoInfo_t >& list ) = 0;
virtual void AddUndoElement( IUndoElement *pElement ) = 0;
virtual UtlSymId_t GetUndoDescInternal( const char *context ) = 0;
virtual UtlSymId_t GetRedoDescInternal( const char *context ) = 0;
virtual void EmptyClipboard() = 0;
virtual void SetClipboardData( CUtlVector< KeyValues * >& data, IClipboardCleanup *pfnOptionalCleanuFunction = 0 ) = 0;
virtual void AddToClipboardData( KeyValues *add ) = 0;
virtual void GetClipboardData( CUtlVector< KeyValues * >& data ) = 0;
virtual bool HasClipboardData() const = 0;
// Handles to attributes
virtual CDmAttribute * GetAttribute( DmAttributeHandle_t h ) = 0;
virtual bool IsAttributeHandleValid( DmAttributeHandle_t h ) const = 0;
// file id reference methods
virtual int NumFileIds() = 0;
virtual DmFileId_t GetFileId( int i ) = 0;
virtual DmFileId_t FindOrCreateFileId( const char *pFilename ) = 0;
virtual void RemoveFileId( DmFileId_t fileid ) = 0;
virtual DmFileId_t GetFileId( const char *pFilename ) = 0;
virtual const char * GetFileName( DmFileId_t fileid ) = 0;
virtual void SetFileName( DmFileId_t fileid, const char *pFileName ) = 0;
virtual const char * GetFileFormat( DmFileId_t fileid ) = 0;
virtual void SetFileFormat( DmFileId_t fileid, const char *pFormat ) = 0;
virtual DmElementHandle_t GetFileRoot( DmFileId_t fileid ) = 0;
virtual void SetFileRoot( DmFileId_t fileid, DmElementHandle_t hRoot ) = 0;
virtual bool IsFileLoaded( DmFileId_t fileid ) = 0;
virtual void MarkFileLoaded( DmFileId_t fileid ) = 0;
virtual void UnloadFile( DmFileId_t fileid ) = 0;
virtual int NumElementsInFile( DmFileId_t fileid ) = 0;
virtual void DontAutoDelete( DmElementHandle_t hElement ) = 0;
// handle validity methods - these shouldn't really be here, but the undo system needs them...
virtual void MarkHandleInvalid( DmElementHandle_t hElement ) = 0;
virtual void MarkHandleValid( DmElementHandle_t hElement ) = 0;
virtual DmElementHandle_t FindElement( const DmObjectId_t &id ) = 0;
virtual DmAttributeReferenceIterator_t FirstAttributeReferencingElement( DmElementHandle_t hElement ) = 0;
virtual DmAttributeReferenceIterator_t NextAttributeReferencingElement( DmAttributeReferenceIterator_t hAttrIter ) = 0;
virtual CDmAttribute * GetAttribute( DmAttributeReferenceIterator_t hAttrIter ) = 0;
// Install, remove notify callbacks associated w/ undo contexts
virtual bool InstallNotificationCallback( IDmNotify *pNotify ) = 0;
virtual void RemoveNotificationCallback( IDmNotify *pNotify ) = 0;
virtual bool IsSuppressingNotify( ) const = 0;
virtual void SetSuppressingNotify( bool bSuppress ) = 0;
virtual void PushNotificationScope( const char *pReason, int nNotifySource, int nNotifyFlags ) = 0;
virtual void PopNotificationScope( bool bAbort = false ) = 0;
virtual const char *GetUndoString( UtlSymId_t sym ) = 0;
virtual bool HasElementFactory( const char *pElementType ) const = 0;
// Call before you make any undo records
virtual void SetUndoDepth( int nSize ) = 0;
// Displats memory stats to the console
virtual void DisplayMemoryStats() = 0;
};
//-----------------------------------------------------------------------------
// Used only by applications to hook in the data model
//-----------------------------------------------------------------------------
#define VDATAMODEL_INTERFACE_VERSION "VDataModelVersion001"
//-----------------------------------------------------------------------------
// Main interface accessor
//-----------------------------------------------------------------------------
extern IDataModel *g_pDataModel;
//-----------------------------------------------------------------------------
// Allows clients to implement customized undo elements
//-----------------------------------------------------------------------------
class CUndoElement : public IUndoElement
{
public:
CUndoElement( const char *pDesc )
{
m_UndoDesc = g_pDataModel->GetUndoDescInternal( pDesc );
m_RedoDesc = g_pDataModel->GetRedoDescInternal( pDesc );
m_pDesc = pDesc;
m_bEndOfStream = false;
}
virtual void Release()
{
delete this;
}
virtual const char *UndoDesc() const
{
return g_pDataModel->GetUndoString( m_UndoDesc );
}
virtual const char *RedoDesc() const
{
return g_pDataModel->GetUndoString( m_RedoDesc );
}
virtual const char *GetDesc() const
{
return m_pDesc;
}
protected:
virtual bool IsEndOfStream() const
{
return m_bEndOfStream;
}
virtual void SetEndOfStream( bool end )
{
m_bEndOfStream = end;
}
const char *m_pDesc;
CUtlSymbol m_UndoDesc;
CUtlSymbol m_RedoDesc;
bool m_bEndOfStream;
private:
friend class CUndoManager;
};
//-----------------------------------------------------------------------------
// Purpose: Simple helper class
//-----------------------------------------------------------------------------
class CUndoScopeGuard
{
public:
explicit CUndoScopeGuard( const char *udesc, const char *rdesc = NULL )
{
m_bReleased = false;
m_bNotify = false;
m_pNotify = NULL;
g_pDataModel->StartUndo( udesc, rdesc ? rdesc : udesc );
}
explicit CUndoScopeGuard( int nChainingID, char const *udesc )
{
m_bReleased = false;
m_bNotify = false;
m_pNotify = NULL;
g_pDataModel->StartUndo( udesc, udesc, nChainingID );
}
explicit CUndoScopeGuard( int nNotifySource, int nNotifyFlags, const char *udesc, const char *rdesc = NULL, int nChainingID = 0 )
{
m_bReleased = false;
m_bNotify = true;
m_pNotify = NULL;
g_pDataModel->StartUndo( udesc, rdesc ? rdesc : udesc, nChainingID );
g_pDataModel->PushNotificationScope( udesc, nNotifySource, nNotifyFlags );
}
explicit CUndoScopeGuard( int nNotifySource, int nNotifyFlags, IDmNotify *pNotify, const char *udesc, const char *rdesc = NULL, int nChainingID = 0 )
{
m_bReleased = false;
m_bNotify = true;
m_pNotify = NULL;
g_pDataModel->StartUndo( udesc, rdesc ? rdesc : udesc, nChainingID );
if ( pNotify )
{
if ( g_pDataModel->InstallNotificationCallback( pNotify ) )
{
m_pNotify = pNotify;
}
}
g_pDataModel->PushNotificationScope( udesc, nNotifySource, nNotifyFlags );
}
~CUndoScopeGuard()
{
Release();
}
void Release()
{
if ( !m_bReleased )
{
g_pDataModel->FinishUndo();
if ( m_bNotify )
{
g_pDataModel->PopNotificationScope( );
m_bNotify = false;
}
if ( m_pNotify )
{
g_pDataModel->RemoveNotificationCallback( m_pNotify );
m_pNotify = NULL;
}
m_bReleased = true;
}
}
void Abort()
{
if ( !m_bReleased )
{
g_pDataModel->AbortUndoableOperation();
if ( m_bNotify )
{
g_pDataModel->PopNotificationScope( true );
m_bNotify = false;
}
if ( m_pNotify )
{
g_pDataModel->RemoveNotificationCallback( m_pNotify );
m_pNotify = NULL;
}
m_bReleased = true;
}
}
private:
IDmNotify *m_pNotify;
bool m_bReleased;
bool m_bNotify;
};
//-----------------------------------------------------------------------------
// Purpose: Simple helper class to disable Undo/Redo operations when in scope
//-----------------------------------------------------------------------------
class CChangeUndoScopeGuard
{
public:
CChangeUndoScopeGuard( bool bNewState )
{
m_bReleased = false;
m_bNotify = false;
m_pNotify = NULL;
m_bOldValue = g_pDataModel->IsUndoEnabled();
g_pDataModel->SetUndoEnabled( bNewState );
};
CChangeUndoScopeGuard( bool bNewState, const char *pDesc, int nNotifySource, int nNotifyFlags, IDmNotify *pNotify = NULL )
{
m_bReleased = false;
m_bOldValue = g_pDataModel->IsUndoEnabled();
g_pDataModel->SetUndoEnabled( bNewState );
m_bNotify = true;
m_pNotify = NULL;
if ( pNotify )
{
if ( g_pDataModel->InstallNotificationCallback( pNotify ) )
{
m_pNotify = pNotify;
}
}
g_pDataModel->PushNotificationScope( pDesc, nNotifySource, nNotifyFlags );
};
~CChangeUndoScopeGuard()
{
Release();
}
void Release()
{
// Releases the guard...
if ( !m_bReleased )
{
g_pDataModel->SetUndoEnabled( m_bOldValue );
m_bReleased = true;
if ( m_bNotify )
{
g_pDataModel->PopNotificationScope( );
m_bNotify = false;
}
if ( m_pNotify )
{
g_pDataModel->RemoveNotificationCallback( m_pNotify );
m_pNotify = NULL;
}
}
}
private:
IDmNotify *m_pNotify;
bool m_bOldValue;
bool m_bReleased;
bool m_bNotify;
};
class CDisableUndoScopeGuard : public CChangeUndoScopeGuard
{
typedef CChangeUndoScopeGuard BaseClass;
public:
CDisableUndoScopeGuard() : BaseClass( false ) { }
CDisableUndoScopeGuard( const char *pDesc, int nNotifySource, int nNotifyFlags, IDmNotify *pNotify = NULL ) :
BaseClass( false, pDesc, nNotifySource, nNotifyFlags, pNotify ) {}
};
class CEnableUndoScopeGuard : public CChangeUndoScopeGuard
{
typedef CChangeUndoScopeGuard BaseClass;
public:
CEnableUndoScopeGuard( ) : BaseClass( true ) { }
CEnableUndoScopeGuard( const char *pDesc, int nNotifySource, int nNotifyFlags, IDmNotify *pNotify = NULL ) :
BaseClass( true, pDesc, nNotifySource, nNotifyFlags, pNotify ) {}
};
#define DEFINE_SOURCE_UNDO_SCOPE_GUARD( _classnameprefix, _source ) \
class C ## _classnameprefix ## UndoScopeGuard : public CUndoScopeGuard \
{ \
typedef CUndoScopeGuard BaseClass; \
\
public: \
C ## _classnameprefix ## UndoScopeGuard( int nNotifyFlags, const char *pUndoDesc, const char *pRedoDesc = NULL, int nChainingID = 0 ) : \
BaseClass( _source, nNotifyFlags, pUndoDesc, pRedoDesc, nChainingID ) \
{ \
} \
C ## _classnameprefix ## UndoScopeGuard( int nNotifyFlags, IDmNotify *pNotify, const char *pUndoDesc, const char *pRedoDesc = NULL, int nChainingID = 0 ) : \
BaseClass( _source, nNotifyFlags, pNotify, pUndoDesc, pRedoDesc, nChainingID ) \
{ \
} \
C ## _classnameprefix ## UndoScopeGuard( int nNotifyFlags, const char *pUndoDesc, int nChainingID ) : \
BaseClass( _source, nNotifyFlags, pUndoDesc, pUndoDesc, nChainingID ) \
{ \
} \
}; \
class C ## _classnameprefix ## DisableUndoScopeGuard : public CDisableUndoScopeGuard \
{ \
typedef CDisableUndoScopeGuard BaseClass; \
\
public: \
C ## _classnameprefix ## DisableUndoScopeGuard( const char *pDesc, int nNotifyFlags, IDmNotify *pNotify = NULL ) : \
BaseClass( pDesc, _source, nNotifyFlags, pNotify ) \
{ \
} \
}; \
class C ## _classnameprefix ## EnableUndoScopeGuard : public CEnableUndoScopeGuard \
{ \
typedef CEnableUndoScopeGuard BaseClass; \
\
public: \
C ## _classnameprefix ## EnableUndoScopeGuard( const char *pDesc, int nNotifyFlags, IDmNotify *pNotify = NULL ) : \
BaseClass( pDesc, _source, nNotifyFlags, pNotify ) \
{ \
} \
}
//-----------------------------------------------------------------------------
// Purpose: Simple helper class to disable NotifyDataChanged from current scope
//-----------------------------------------------------------------------------
class CNotifyScopeGuard
{
public:
CNotifyScopeGuard( const char *pReason, int nNotifySource, int nNotifyFlags, IDmNotify *pNotify = NULL )
{
m_bReleased = false;
m_pNotify = NULL;
g_pDataModel->PushNotificationScope( pReason, nNotifySource, nNotifyFlags );
if ( pNotify )
{
if ( g_pDataModel->InstallNotificationCallback( pNotify ) )
{
m_pNotify = pNotify;
}
}
};
~CNotifyScopeGuard()
{
Release();
}
void Release()
{
// Releases the guard...
if ( !m_bReleased )
{
g_pDataModel->PopNotificationScope( );
if ( m_pNotify )
{
g_pDataModel->RemoveNotificationCallback( m_pNotify );
m_pNotify = NULL;
}
m_bReleased = true;
}
}
private:
CNotifyScopeGuard( const CNotifyScopeGuard& g );
private:
IDmNotify *m_pNotify;
bool m_bReleased;
};
#define DEFINE_SOURCE_NOTIFY_SCOPE_GUARD( _classnameprefix, _source ) \
class C ## _classnameprefix ## NotifyScopeGuard : public CNotifyScopeGuard \
{ \
typedef CNotifyScopeGuard BaseClass; \
\
public: \
C ## _classnameprefix ## NotifyScopeGuard( const char *pReason, int nNotifyFlags, IDmNotify *pNotify = NULL ) : \
BaseClass( pReason, _source, nNotifyFlags, pNotify )\
{ \
} \
}
//-----------------------------------------------------------------------------
// Purpose: Simple helper class to disable notifications when in scope
//-----------------------------------------------------------------------------
class CChangeNotifyScopeGuard
{
public:
CChangeNotifyScopeGuard( bool bNewState )
{
m_bReleased = false;
m_bOldValue = g_pDataModel->IsSuppressingNotify();
g_pDataModel->SetSuppressingNotify( bNewState );
};
~CChangeNotifyScopeGuard()
{
Release();
}
void Release()
{
// Releases the guard...
if ( !m_bReleased )
{
g_pDataModel->SetSuppressingNotify( m_bOldValue );
m_bReleased = true;
}
}
private:
bool m_bOldValue;
bool m_bReleased;
};
class CDisableNotifyScopeGuard : public CChangeNotifyScopeGuard
{
typedef CChangeNotifyScopeGuard BaseClass;
public:
CDisableNotifyScopeGuard() : BaseClass( true ) { }
private:
CDisableNotifyScopeGuard( const CDisableNotifyScopeGuard& g );
};
class CEnableNotifyScopeGuard : public CChangeNotifyScopeGuard
{
typedef CChangeNotifyScopeGuard BaseClass;
public:
CEnableNotifyScopeGuard( ) : BaseClass( false ) { }
private:
CEnableNotifyScopeGuard( const CEnableNotifyScopeGuard& g );
};
//-----------------------------------------------------------------------------
// Standard undo/notify guards for the application
//-----------------------------------------------------------------------------
DEFINE_SOURCE_UNDO_SCOPE_GUARD( App, NOTIFY_SOURCE_APPLICATION );
DEFINE_SOURCE_NOTIFY_SCOPE_GUARD( App, NOTIFY_SOURCE_APPLICATION );
#endif // IDATAMODEL_H

View File

@ -0,0 +1,250 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef DEMOFORMAT_H
#define DEMOFORMAT_H
#ifdef _WIN32
#pragma once
#endif
#include "mathlib/vector.h"
#include "utlvector.h"
#include "tier0/platform.h"
#define DEMO_HEADER_ID "HL2DEMO"
#define DEMO_PROTOCOL 3
#if !defined( MAX_OSPATH )
#define MAX_OSPATH 260 // max length of a filesystem pathname
#endif
// Demo messages
enum
{
// it's a startup message, process as fast as possible
dem_signon = 1,
// it's a normal network packet that we stored off
dem_packet,
// sync client clock to demo tick
dem_synctick,
// console command
dem_consolecmd,
// user input command
dem_usercmd,
// network data tables
dem_datatables,
// end of time.
dem_stop,
dem_stringtables,
// Last command
dem_lastcmd = dem_stringtables
};
struct demoheader_t
{
char demofilestamp[8]; // Should be HL2DEMO
int demoprotocol; // Should be DEMO_PROTOCOL
int networkprotocol; // Should be PROTOCOL_VERSION
char servername[ MAX_OSPATH ]; // Name of server
char clientname[ MAX_OSPATH ]; // Name of client who recorded the game
char mapname[ MAX_OSPATH ]; // Name of map
char gamedirectory[ MAX_OSPATH ]; // Name of game directory (com_gamedir)
float playback_time; // Time of track
int playback_ticks; // # of ticks in track
int playback_frames; // # of frames in track
int signonlength; // length of sigondata in bytes
};
inline void ByteSwap_demoheader_t( demoheader_t &swap )
{
swap.demoprotocol = LittleDWord( swap.demoprotocol );
swap.networkprotocol = LittleDWord( swap.networkprotocol );
LittleFloat( &swap.playback_time, &swap.playback_time );
swap.playback_ticks = LittleDWord( swap.playback_ticks );
swap.playback_frames = LittleDWord( swap.playback_frames );
swap.signonlength = LittleDWord( swap.signonlength );
}
#define FDEMO_NORMAL 0
#define FDEMO_USE_ORIGIN2 (1<<0)
#define FDEMO_USE_ANGLES2 (1<<1)
#define FDEMO_NOINTERP (1<<2) // don't interpolate between this an last view
struct democmdinfo_t
{
// Default constructor
democmdinfo_t()
{
flags = FDEMO_NORMAL;
viewOrigin.Init();
viewAngles.Init();
localViewAngles.Init();
// Resampled origin/angles
viewOrigin2.Init();
viewAngles2.Init();
localViewAngles2.Init();
}
// Copy constructor
// Assignment
democmdinfo_t& operator=(const democmdinfo_t& src )
{
if ( this == &src )
return *this;
flags = src.flags;
viewOrigin = src.viewOrigin;
viewAngles = src.viewAngles;
localViewAngles = src.localViewAngles;
viewOrigin2 = src.viewOrigin2;
viewAngles2 = src.viewAngles2;
localViewAngles2 = src.localViewAngles2;
return *this;
}
const Vector& GetViewOrigin()
{
if ( flags & FDEMO_USE_ORIGIN2 )
{
return viewOrigin2;
}
return viewOrigin;
}
const QAngle& GetViewAngles()
{
if ( flags & FDEMO_USE_ANGLES2 )
{
return viewAngles2;
}
return viewAngles;
}
const QAngle& GetLocalViewAngles()
{
if ( flags & FDEMO_USE_ANGLES2 )
{
return localViewAngles2;
}
return localViewAngles;
}
void Reset( void )
{
flags = 0;
viewOrigin2 = viewOrigin;
viewAngles2 = viewAngles;
localViewAngles2 = localViewAngles;
}
int flags;
// original origin/viewangles
Vector viewOrigin;
QAngle viewAngles;
QAngle localViewAngles;
// Resampled origin/viewangles
Vector viewOrigin2;
QAngle viewAngles2;
QAngle localViewAngles2;
};
struct demosmoothing_t
{
demosmoothing_t()
{
file_offset = 0;
frametick = 0;
selected = false;
samplepoint = false;
vecmoved.Init();
angmoved.Init();
targetpoint = false;
vectarget.Init();
}
demosmoothing_t& operator=(const demosmoothing_t& src )
{
if ( this == &src )
return *this;
file_offset = src.file_offset;
frametick = src.frametick;
selected = src.selected;
samplepoint = src.samplepoint;
vecmoved = src.vecmoved;
angmoved = src.angmoved;
targetpoint = src.targetpoint;
vectarget = src.vectarget;
info = src.info;
return *this;
}
int file_offset;
int frametick;
bool selected;
// For moved sample points
bool samplepoint;
Vector vecmoved;
QAngle angmoved;
bool targetpoint;
Vector vectarget;
democmdinfo_t info;
};
struct CSmoothingContext
{
CSmoothingContext()
{
active = false;
filename[ 0 ] = 0;
m_nFirstSelectableSample = 0;
}
CSmoothingContext& operator=(const CSmoothingContext& src )
{
if ( this == &src )
return *this;
active = src.active;
Q_strncpy( filename, src.filename, sizeof( filename ) );
smooth.RemoveAll();
int c = src.smooth.Count();
int i;
for ( i = 0; i < c; i++ )
{
demosmoothing_t newitem;
newitem = src.smooth[ i ];
smooth.AddToTail( newitem );
}
m_nFirstSelectableSample = src.m_nFirstSelectableSample;
return *this;
}
bool active;
char filename[ 512 ];
CUtlVector< demosmoothing_t > smooth;
int m_nFirstSelectableSample;
};
#endif // DEMOFORMAT_H

1296
public/disp_common.cpp Normal file

File diff suppressed because it is too large Load Diff

262
public/disp_common.h Normal file
View File

@ -0,0 +1,262 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef DISP_COMMON_H
#define DISP_COMMON_H
#ifdef _WIN32
#pragma once
#endif
#include "disp_vertindex.h"
#include "bspfile.h"
#include "utlvector.h"
class CPowerInfo;
class CCoreDispInfo;
// ----------------------------------------------------------------------------- //
// Classes.
// ----------------------------------------------------------------------------- //
// This class provides a set of utility functions for displacements that work in the tools and the engine.
abstract_class CDispUtilsHelper
{
// Derived classes must implement these.
public:
virtual const CPowerInfo* GetPowerInfo() const = 0;
virtual CDispNeighbor* GetEdgeNeighbor( int index ) = 0;
virtual CDispCornerNeighbors* GetCornerNeighbors( int index ) = 0;
virtual CDispUtilsHelper* GetDispUtilsByIndex( int index ) = 0;
// Helper functions.
public:
int GetPower() const;
int GetSideLength() const;
const CVertIndex& GetCornerPointIndex( int iCorner ) const;
int VertIndexToInt( const CVertIndex &i ) const;
CVertIndex GetEdgeMidPoint( int iEdge ) const;
};
// Use this to walk along two neighboring displacements and touch all the
// common vertices.
class CDispSubEdgeIterator
{
public:
CDispSubEdgeIterator();
// Normally, this will iterate all shared verts along the edge except the corners.
// If you want the corners to be touched too, then pass in bTouchCorners=true.
void Start( CDispUtilsHelper *pDisp, int iEdge, int iSub, bool bTouchCorners = false );
bool Next();
const CVertIndex& GetVertIndex() const { return m_Index; } // Get the vert index for the displacement in pUtils.
const CVertIndex& GetNBVertIndex() const { return m_NBIndex; } // Get the neighbor's vert index.
CDispUtilsHelper* GetNeighbor() const { return m_pNeighbor; }
// Returns true if you're on the last vert (ie: the next Next() call will return false).ssssss
bool IsLastVert() const;
private:
CDispUtilsHelper *m_pNeighbor; // The neighbor to the edge we were setup on.
CVertIndex m_Index;
CVertIndex m_Inc;
CVertIndex m_NBIndex;
CVertIndex m_NBInc;
int m_End;
int m_FreeDim;
};
// Use this to walk along the edge of a displacement, touching the points in common
// between the two neighbors. Note: this won't hit the corner points of any of the displacements.
// (As a result, it won't hit the midpoint of pDisps's edge if there are 2 neighbors).
class CDispEdgeIterator
{
public:
CDispEdgeIterator( CDispUtilsHelper *pDisp, int iEdge );
// Seek to the next point on the edge.
bool Next();
const CVertIndex& GetVertIndex() const { return m_It.GetVertIndex(); } // Get the vert index for the displacement in pUtils.
const CVertIndex& GetNBVertIndex() const { return m_It.GetNBVertIndex(); } // Get the neighbor's vert index.
// What is the current neighbor?
CDispUtilsHelper* GetCurrentNeighbor() const { return m_It.GetNeighbor(); }
private:
CDispUtilsHelper *m_pDisp;
int m_iEdge;
int m_iCurSub;
CDispSubEdgeIterator m_It;
};
// Use this to walk all the corners and edge verts in the displacement.
// It walks the edges in the order of the NEIGHBOREDGE_ defines.
// Iterate like this:
// CDispCircumferenceIterator iterator( pDisp->GetSideLength() );
// while ( iterator.Next() )
// ...
class CDispCircumferenceIterator
{
public:
CDispCircumferenceIterator( int sideLength );
// Seek to the next point. Returns false when there are no more points.
bool Next();
const CVertIndex& GetVertIndex() const { return m_VertIndex; }
private:
int m_SideLengthM1;
int m_iCurEdge;
CVertIndex m_VertIndex;
};
// These store info about how to scale and shift coordinates between neighbors
// of different relations (in g_ShiftInfos).
class CShiftInfo
{
public:
int m_MidPointScale;
int m_PowerShiftAdd;
bool m_bValid;
};
class CDispBox
{
public:
Vector m_Min, m_Max;
};
// ----------------------------------------------------------------------------- //
// Globals.
// ----------------------------------------------------------------------------- //
extern int g_EdgeDims[4]; // This tells which dimension (0 or 1) is locked on an edge for each NEIGHBOREDGE_ enum.
extern CShiftInfo g_ShiftInfos[3][3]; // See CShiftInfo.
extern int g_EdgeSideLenMul[4];// Multiply these by the side length to get the index of the edge.
// ----------------------------------------------------------------------------- //
// Helper functions.
// ----------------------------------------------------------------------------- //
// Reference implementation to generate triangle indices for a displacement.
int DispCommon_GetNumTriIndices( int power );
void DispCommon_GenerateTriIndices( int power, unsigned short *indices );
// Returns a NEIGHBOREDGE_ value for the edge that the index is on.
// Returns -1 if the index is not on a side.
// If the point is on a corner, the edges are tested in the order of the NEIGHBOREDGE_ defines.
int GetEdgeIndexFromPoint( CVertIndex const &index, int iPower );
// Returns a CORNER_ value for the corner the point is on, or -1 if it's not on a corner.
int GetEdgeIndexFromPoint( CVertIndex const &index, int iPower );
// This returns the neighbor's power, possibly +1 or -1.
//
// It will add one if the neighbor takes up half of your edge (ie: if it took up your
// whole edge, its resolution would be twice what it really is).
//
// It will subtract one if you take up half of its edge (ie: you only touch half of its verts).
//
// Returns -1 if the edge connection is invalid.
int GetNeighborEdgePower( CDispUtilsHelper *pDisp, int iEdge, int iSub );
// This function sets you up so you can walk along an edge that joins two neighbors.
// Add myInc to myIndex and nbInc to nbIndex until myIndex[iFreeDim] >= myEnd.
//
// Returns the neighbor displacement, or NULL if the specified sub neighbor isn't valid.
CDispUtilsHelper* SetupEdgeIncrements(
CDispUtilsHelper *pDisp,
int iEdge,
int iSub,
CVertIndex &myIndex,
CVertIndex &myInc,
CVertIndex &nbIndex,
CVertIndex &nbInc,
int &myEnd,
int &iFreeDim );
// Figure out which sub neighbor nodeIndex touches.
// Returns -1 if there is no valid sub neighbor at the specified index.
int GetSubNeighborIndex(
CDispUtilsHelper *pDisp,
int iEdge,
CVertIndex const &nodeIndex
);
// Given a vert index and the CSubNeighbor the vert lies on, this
// transforms the specified vert into the neighbor's space.
//
// Note: for corner verts, there may be multiple neighbors touching the same vert, so the
// result you get depends on the edge you specify in iEdge (ie: if you specify the same
// node index but a different edge, you may get a different neighbor).
//
// Note: This only returns a point if the point at nodeIndex actually touches a neighbor point.
// An example where this might be unexpected is if pDisp is power 4 and its neighbor on iEdge
// is power 3, and nodeIndex points at a vert in between two of its neighbor's verts.
// In that case, even though there is a neighbor displacement, nodeIndex doesn't touch
// any points on it, so NULL is returned.
CDispUtilsHelper* TransformIntoSubNeighbor(
CDispUtilsHelper *pDisp,
int iEdge,
int iSub,
CVertIndex const &nodeIndex,
CVertIndex &out
);
// Transform pDisp's node at nodeIndex into its neighboring connection.
// Returns the neighbor displacement and sets out to the index in the neighbor.
//
// Note: for corner verts, there may be multiple neighbors touching the same vert, so the
// result you get depends on the edge you specify in iEdge (ie: if you specify the same
// node index but a different edge, you may get a different neighbor).
//
// Note: This only returns a point if the point at nodeIndex actually touches a neighbor point.
// An example where this might surprise you is if pDisp is power 4 and its neighbor on iEdge
// is power 3, and nodeIndex points at a vert in between two of its neighbor's verts.
// In that case, even though there is a neighbor displacement, nodeIndex doesn't touch
// any points on it, so NULL is returned.
CDispUtilsHelper* TransformIntoNeighbor(
CDispUtilsHelper *pDisp,
int iEdge,
CVertIndex const &nodeIndex,
CVertIndex &out );
// Returns true if the specified point has one or more neighbors.
bool DoesPointHaveAnyNeighbors(
CDispUtilsHelper *pDisp,
const CVertIndex &index );
void FindNeighboringDispSurfs( CCoreDispInfo **ppListBase, int nListSize );
void SetupAllowedVerts( CCoreDispInfo **ppListBase, int nListSize );
void GetDispBox( CCoreDispInfo *pDisp, CDispBox &box );
// ----------------------------------------------------------------------------- //
// Inlines.
// ----------------------------------------------------------------------------- //
#include "disp_powerinfo.h"
#endif // DISP_COMMON_H

580
public/disp_powerinfo.cpp Normal file
View File

@ -0,0 +1,580 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "disp_powerinfo.h"
#include "disp_common.h"
#include "commonmacros.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// ------------------------------------------------------------------------ //
// Internal classes.
// ------------------------------------------------------------------------ //
// These point at the vertices connecting to each of the [north,south,east,west] vertices.
class CVertCorners
{
public:
short m_Corner1[2];
short m_Corner2[2];
};
// ------------------------------------------------------------------------ //
// Globals.
// ------------------------------------------------------------------------ //
// This points at vertices to the side of a node (north, south, east, west).
static short g_SideVertMul[4][2] = { {1,0}, {0,1}, {-1,0}, {0,-1} };
static CVertCorners g_SideVertCorners[4] =
{
{ {1,-1}, {1,1} },
{ {1,1}, {-1,1} },
{ {-1,1}, {-1,-1} },
{ {-1,-1}, {1,-1} }
};
// This is used in loops on child nodes. The indices point at the nodes:
// 0 = upper-right
// 1 = upper-left
// 2 = lower-left
// 3 = lower-right
static CVertIndex g_ChildNodeIndexMul[4] =
{
CVertIndex(1,1),
CVertIndex(-1,1),
CVertIndex(-1,-1),
CVertIndex(1,-1)
};
// These are multipliers on vertMul (not nodeMul).
static CVertIndex g_ChildNodeDependencies[4][2] =
{
{ CVertIndex(1,0), CVertIndex(0,1) },
{ CVertIndex(0,1), CVertIndex(-1,0) },
{ CVertIndex(-1,0), CVertIndex(0,-1) },
{ CVertIndex(0,-1), CVertIndex(1,0) }
};
// 2x2 rotation matrices for each orientation.
static int g_OrientationRotations[4][2][2] =
{
{{1, 0}, // CCW_0
{0, 1}},
{{0, 1}, // CCW_90
{-1,0}},
{{-1,0}, // CCW_180
{0,-1}},
{{0, -1}, // CCW_270
{1, 0}}
};
// ------------------------------------------------------------------------ //
// Helper functions.
// ------------------------------------------------------------------------ //
// Apply a 2D rotation to the specified CVertIndex around the specified centerpoint.
static CVertIndex Transform2D(
int const mat[2][2],
CVertIndex const &vert,
CVertIndex const &centerPoint )
{
CVertIndex translated = vert - centerPoint;
CVertIndex transformed(
translated.x*mat[0][0] + translated.y*mat[0][1],
translated.x*mat[1][0] + translated.y*mat[1][1] );
return transformed + centerPoint;
}
// Rotate a given CVertIndex with a specified orientation.
// Do this with a lookup table eventually!
static void GetEdgeVertIndex( int sideLength, int iEdge, int iVert, CVertIndex &out )
{
if( iEdge == NEIGHBOREDGE_RIGHT )
{
out.x = sideLength - 1;
out.y = iVert;
}
else if( iEdge == NEIGHBOREDGE_TOP )
{
out.x = iVert;
out.y = sideLength - 1;
}
else if( iEdge == NEIGHBOREDGE_LEFT )
{
out.x = 0;
out.y = iVert;
}
else
{
out.x = iVert;
out.y = 0;
}
}
// Generate an index given a CVertIndex and the size of the displacement it resides in.
static int VertIndex( CVertIndex const &vert, int iMaxPower )
{
return vert.y * ((1 << iMaxPower) + 1) + vert.x;
}
static CVertIndex WrapVertIndex( CVertIndex const &in, int sideLength )
{
int out[2];
for( int i=0; i < 2; i++ )
{
if( in[i] < 0 )
out[i] = sideLength - 1 - (-in[i] % sideLength);
else if( in[i] >= sideLength )
out[i] = in[i] % sideLength;
else
out[i] = in[i];
}
return CVertIndex( out[0], out[1] );
}
static int GetFreeDependency( CVertDependency *pDep, int nElements )
{
for( int i=0; i < nElements; i++ )
{
if( !pDep[i].IsValid() )
return i;
}
Assert( false );
return 0;
}
static void AddDependency(
CVertInfo *dependencies,
int sideLength,
CVertIndex const &nodeIndex,
CVertIndex const &dependency,
int iMaxPower,
bool bCheckNeighborDependency,
bool bAddReverseDependency )
{
int iNodeIndex = VertIndex( nodeIndex, iMaxPower );
CVertInfo *pNode = &dependencies[iNodeIndex];
int iDep = GetFreeDependency( pNode->m_Dependencies, sizeof(pNode->m_Dependencies)/sizeof(pNode->m_Dependencies[0]) );
pNode->m_Dependencies[iDep].m_iVert = dependency;
pNode->m_Dependencies[iDep].m_iNeighbor = -1;
if( bAddReverseDependency )
{
CVertInfo *pDep = &dependencies[VertIndex( dependency, iMaxPower )];
iDep = GetFreeDependency( pDep->m_ReverseDependencies, CVertInfo::NUM_REVERSE_DEPENDENCIES );
pDep->m_ReverseDependencies[iDep].m_iVert = nodeIndex;
pDep->m_ReverseDependencies[iDep].m_iNeighbor = -1;
}
// Edge verts automatically add a dependency for the neighbor.
// Internal verts wind up in here twice anyway so it doesn't need to
if( bCheckNeighborDependency )
{
int iConnection = GetEdgeIndexFromPoint( nodeIndex, iMaxPower );
if( iConnection != -1 )
{
Assert( !pNode->m_Dependencies[1].IsValid() );
CVertIndex delta( nodeIndex.x - dependency.x, nodeIndex.y - dependency.y );
CVertIndex newIndex( nodeIndex.x + delta.x, nodeIndex.y + delta.y );
int fullSideLength = (1 << iMaxPower) + 1;
pNode->m_Dependencies[1].m_iVert = WrapVertIndex( CVertIndex( newIndex.x, newIndex.y ), fullSideLength );
pNode->m_Dependencies[1].m_iNeighbor = iConnection;
}
}
}
// --------------------------------------------------------------------------------- //
// CTesselateWinding stuff.
// --------------------------------------------------------------------------------- //
CTesselateVert::CTesselateVert( CVertIndex const &index, int iNode )
: m_Index( index )
{
m_iNode = iNode;
}
CVertInfo::CVertInfo()
{
int i;
for( i=0; i < sizeof(m_Dependencies)/sizeof(m_Dependencies[0]); i++ )
{
m_Dependencies[i].m_iVert = CVertIndex( -1, -1 );
m_Dependencies[i].m_iNeighbor = -1;
}
for( i=0; i < sizeof(m_ReverseDependencies)/sizeof(m_ReverseDependencies[0]); i++ )
{
m_ReverseDependencies[i].m_iVert = CVertIndex( -1, -1 );
m_ReverseDependencies[i].m_iNeighbor = -1;
}
m_iParent.x = m_iParent.y = -1;
m_iNodeLevel = -1;
}
CTesselateVert g_TesselateVerts[] =
{
CTesselateVert( CVertIndex(1,-1), CHILDNODE_LOWER_RIGHT),
CTesselateVert( CVertIndex(0,-1), -1),
CTesselateVert( CVertIndex(-1,-1), CHILDNODE_LOWER_LEFT),
CTesselateVert( CVertIndex(-1, 0), -1),
CTesselateVert( CVertIndex(-1, 1), CHILDNODE_UPPER_LEFT),
CTesselateVert( CVertIndex(0, 1), -1),
CTesselateVert( CVertIndex(1, 1), CHILDNODE_UPPER_RIGHT),
CTesselateVert( CVertIndex(1, 0), -1),
CTesselateVert( CVertIndex(1,-1), CHILDNODE_LOWER_RIGHT)
};
CTesselateWinding g_TWinding =
{
g_TesselateVerts,
sizeof( g_TesselateVerts ) / sizeof( g_TesselateVerts[0] )
};
// --------------------------------------------------------------------------------- //
// CPowerInfo stuff.
// --------------------------------------------------------------------------------- //
// Precalculated info about each particular displacement size.
#define DECLARE_TABLES( size ) \
static CVertInfo g_VertInfo_##size##x##size[ size*size ]; \
static CFourVerts g_SideVerts_##size##x##size[ size*size ]; \
static CFourVerts g_ChildVerts_##size##x##size[ size*size ]; \
static CFourVerts g_SideVertCorners_##size##x##size[ size*size ]; \
static CTwoUShorts g_ErrorEdges_##size##x##size[ size*size ]; \
static CTriInfo g_TriInfos_##size##x##size[ (size-1)*(size-1)*2 ]; \
static CPowerInfo g_PowerInfo_##size##x##size( \
g_VertInfo_##size##x##size, \
g_SideVerts_##size##x##size, \
g_ChildVerts_##size##x##size, \
g_SideVertCorners_##size##x##size,\
g_ErrorEdges_##size##x##size, \
g_TriInfos_##size##x##size \
)
#define POWERINFO_ENTRY( size ) \
(&g_PowerInfo_##size##x##size)
DECLARE_TABLES( 5 );
DECLARE_TABLES( 9 );
DECLARE_TABLES( 17 );
// Index by m_Power.
CPowerInfo *g_PowerInfos[NUM_POWERINFOS] =
{
NULL,
NULL,
POWERINFO_ENTRY(5),
POWERINFO_ENTRY(9),
POWERINFO_ENTRY(17)
};
CPowerInfo::CPowerInfo(
CVertInfo *pVertInfo,
CFourVerts *pSideVerts,
CFourVerts *pChildVerts,
CFourVerts *pSideVertCorners,
CTwoUShorts *pErrorEdges,
CTriInfo *pTriInfos )
{
m_pVertInfo = pVertInfo;
m_pSideVerts = pSideVerts;
m_pChildVerts = pChildVerts;
m_pSideVertCorners = pSideVertCorners;
m_pErrorEdges = pErrorEdges;
m_pTriInfos = pTriInfos;
}
static void InitPowerInfoTriInfos_R(
CPowerInfo *pInfo,
CVertIndex const &nodeIndex,
CTriInfo* &pTriInfo,
int iMaxPower,
int iLevel )
{
int iNodeIndex = VertIndex( nodeIndex, iMaxPower );
if( iLevel+1 < iMaxPower )
{
// Recurse into children.
for( int iChild=0; iChild < 4; iChild++ )
{
InitPowerInfoTriInfos_R(
pInfo,
pInfo->m_pChildVerts[iNodeIndex].m_Verts[iChild],
pTriInfo,
iMaxPower,
iLevel+1 );
}
}
else
{
unsigned short indices[3];
int vertInc = 1 << ((iMaxPower - iLevel) - 1);
// We're at a leaf, generate the tris.
CTesselateWinding *pWinding = &g_TWinding;
// Starting at the bottom-left, wind clockwise picking up vertices and
// generating triangles.
int iCurTriVert = 0;
for( int iVert=0; iVert < pWinding->m_nVerts; iVert++ )
{
CVertIndex sideVert = BuildOffsetVertIndex( nodeIndex, pWinding->m_Verts[iVert].m_Index, vertInc );
if( iCurTriVert == 1 )
{
// Add this vert and finish the tri.
pTriInfo->m_Indices[0] = indices[0];
pTriInfo->m_Indices[1] = VertIndex( sideVert, iMaxPower );
pTriInfo->m_Indices[2] = iNodeIndex;
++pTriInfo;
}
indices[0] = VertIndex( sideVert, iMaxPower );
iCurTriVert = 1;
}
}
}
static void InitPowerInfo_R(
CPowerInfo *pPowerInfo,
int iMaxPower,
CVertIndex const &nodeIndex,
CVertIndex const &dependency1,
CVertIndex const &dependency2,
CVertIndex const &nodeEdge1,
CVertIndex const &nodeEdge2,
CVertIndex const &iParent,
int iLevel )
{
int sideLength = ((1 << iMaxPower) + 1);
int iNodeIndex = VertIndex( nodeIndex, iMaxPower );
pPowerInfo->m_pVertInfo[iNodeIndex].m_iParent = iParent;
pPowerInfo->m_pVertInfo[iNodeIndex].m_iNodeLevel = iLevel + 1;
pPowerInfo->m_pErrorEdges[iNodeIndex].m_Values[0] = (unsigned short)(VertIndex( nodeEdge1, iMaxPower ));
pPowerInfo->m_pErrorEdges[iNodeIndex].m_Values[1] = (unsigned short)(VertIndex( nodeEdge2, iMaxPower ));
// Add this node's dependencies.
AddDependency( pPowerInfo->m_pVertInfo, sideLength, nodeIndex, dependency1, iMaxPower, false, true );
AddDependency( pPowerInfo->m_pVertInfo, sideLength, nodeIndex, dependency2, iMaxPower, false, true );
// The 4 side vertices depend on this node.
int iPower = iMaxPower - iLevel;
int vertInc = 1 << (iPower - 1);
for( int iSide=0; iSide < 4; iSide++ )
{
// Store the side vert index.
CVertIndex sideVert( nodeIndex.x + g_SideVertMul[iSide][0]*vertInc, nodeIndex.y + g_SideVertMul[iSide][1]*vertInc );
int iSideVert = VertIndex( sideVert, iMaxPower );
pPowerInfo->m_pSideVerts[iNodeIndex].m_Verts[iSide] = sideVert;
// Store the side vert corners.
CVertIndex sideVertCorner0 = CVertIndex( nodeIndex.x + g_SideVertCorners[iSide].m_Corner1[0]*vertInc, nodeIndex.y + g_SideVertCorners[iSide].m_Corner1[1]*vertInc );
CVertIndex sideVertCorner1 = CVertIndex( nodeIndex.x + g_SideVertCorners[iSide].m_Corner2[0]*vertInc, nodeIndex.y + g_SideVertCorners[iSide].m_Corner2[1]*vertInc );
pPowerInfo->m_pSideVertCorners[iNodeIndex].m_Verts[iSide] = sideVertCorner0;
// Write the side vert corners into the error-edges list.
pPowerInfo->m_pErrorEdges[iSideVert].m_Values[0] = (unsigned short)VertIndex( sideVertCorner0, iMaxPower );
pPowerInfo->m_pErrorEdges[iSideVert].m_Values[1] = (unsigned short)VertIndex( sideVertCorner1, iMaxPower );
AddDependency(
pPowerInfo->m_pVertInfo,
sideLength,
sideVert,
nodeIndex,
iMaxPower,
true,
true );
}
// Recurse into the children.
int nodeInc = vertInc >> 1;
if( nodeInc )
{
for( int iChild=0; iChild < 4; iChild++ )
{
CVertIndex childVert( nodeIndex.x + g_ChildNodeIndexMul[iChild].x * nodeInc, nodeIndex.y + g_ChildNodeIndexMul[iChild].y * nodeInc );
pPowerInfo->m_pChildVerts[iNodeIndex].m_Verts[iChild] = childVert;
InitPowerInfo_R( pPowerInfo,
iMaxPower,
childVert,
CVertIndex(nodeIndex.x + g_ChildNodeDependencies[iChild][0].x*vertInc, nodeIndex.y + g_ChildNodeDependencies[iChild][0].y*vertInc),
CVertIndex(nodeIndex.x + g_ChildNodeDependencies[iChild][1].x*vertInc, nodeIndex.y + g_ChildNodeDependencies[iChild][1].y*vertInc),
nodeIndex,
CVertIndex( nodeIndex.x + g_ChildNodeIndexMul[iChild].x * vertInc, nodeIndex.y + g_ChildNodeIndexMul[iChild].y * vertInc ),
nodeIndex,
iLevel + 1 );
}
}
}
void InitPowerInfo( CPowerInfo *pInfo, int iMaxPower )
{
int sideLength = (1 << iMaxPower) + 1;
// Precalculate the dependency graph.
CVertIndex nodeDependency1( sideLength-1, sideLength-1 );
CVertIndex nodeDependency2( 0, 0 );
pInfo->m_RootNode = CVertIndex( sideLength/2, sideLength/2 );
pInfo->m_SideLength = sideLength;
pInfo->m_SideLengthM1 = sideLength - 1;
pInfo->m_MidPoint = sideLength / 2;
pInfo->m_MaxVerts = sideLength * sideLength;
// Setup the corner indices.
pInfo->m_CornerPointIndices[CORNER_LOWER_LEFT].Init( 0, 0 );
pInfo->m_CornerPointIndices[CORNER_UPPER_LEFT].Init( 0, sideLength-1 );
pInfo->m_CornerPointIndices[CORNER_UPPER_RIGHT].Init( sideLength-1, sideLength-1 );
pInfo->m_CornerPointIndices[CORNER_LOWER_RIGHT].Init( sideLength-1, 0 );
InitPowerInfo_R(
pInfo,
iMaxPower,
pInfo->m_RootNode,
nodeDependency1, // dependencies
nodeDependency2,
CVertIndex(0,0), // error edge
CVertIndex(sideLength-1, sideLength-1),
CVertIndex(-1,-1), // parent
0 );
pInfo->m_Power = iMaxPower;
CTriInfo *pTriInfo = pInfo->m_pTriInfos;
InitPowerInfoTriInfos_R( pInfo, pInfo->m_RootNode, pTriInfo, iMaxPower, 0 );
for( int iEdge=0; iEdge < 4; iEdge++ )
{
// Figure out the start vert and increment.
CVertIndex nextVert;
GetEdgeVertIndex( sideLength, iEdge, 0, pInfo->m_EdgeStartVerts[iEdge] );
GetEdgeVertIndex( sideLength, iEdge, 1, nextVert );
pInfo->m_EdgeIncrements[iEdge] = nextVert - pInfo->m_EdgeStartVerts[iEdge];
// Now get the neighbor's start vert and increment.
CVertIndex nbStartVert, nbNextVert, nbDelta;
GetEdgeVertIndex( sideLength, (iEdge+2)&3, 0, nbStartVert );
GetEdgeVertIndex( sideLength, (iEdge+2)&3, 1, nbNextVert );
nbDelta = nbNextVert - nbStartVert;
// Rotate it for each orientation.
for( int orient=0; orient < 4; orient++ )
{
pInfo->m_NeighborStartVerts[iEdge][orient] = Transform2D(
g_OrientationRotations[orient],
nbStartVert,
CVertIndex( sideLength/2, sideLength/2 ) );
pInfo->m_NeighborIncrements[iEdge][orient] = Transform2D(
g_OrientationRotations[orient],
nbDelta,
CVertIndex(0,0) );
}
}
// Init the node index increments.
int curPowerOf4 = 1;
int curTotal = 0;
for( int i=0; i < iMaxPower-1; i++ )
{
curTotal += curPowerOf4;
pInfo->m_NodeIndexIncrements[iMaxPower-i-2] = curTotal;
curPowerOf4 *= 4;
}
// Store off the total node count
pInfo->m_NodeCount = curTotal + curPowerOf4;
pInfo->m_nTriInfos = Square( 1 << iMaxPower ) * 2;
}
class CPowerInfoInitializer
{
public:
CPowerInfoInitializer()
{
Assert( MAX_MAP_DISP_POWER+1 == NUM_POWERINFOS );
for( int i=0; i <= MAX_MAP_DISP_POWER; i++ )
{
if( g_PowerInfos[i] )
{
InitPowerInfo( g_PowerInfos[i], i );
}
}
}
};
static CPowerInfoInitializer g_PowerInfoInitializer;
const CPowerInfo* GetPowerInfo( int iPower )
{
Assert( iPower >= 0 && iPower < ARRAYSIZE( g_PowerInfos ) );
Assert( g_PowerInfos[iPower] );
return g_PowerInfos[iPower];
}
// ------------------------------------------------------------------------------------------------ //
// CPowerInfo member function initialization.
// ------------------------------------------------------------------------------------------------ //
const CVertIndex& CPowerInfo::GetCornerPointIndex( int iCorner ) const
{
Assert( iCorner >= 0 && iCorner < 4 );
return m_CornerPointIndices[iCorner];
}

213
public/disp_powerinfo.h Normal file
View File

@ -0,0 +1,213 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: This module defines the CPowerInfo class, which contains a
// whole bunch of precalculated data for each displacement power.
// It holds data that indicates how to tesselate, how to access
// neighbor displacements, etc.
//
// $NoKeywords: $
//=============================================================================//
#ifndef DISP_POWERINFO_H
#define DISP_POWERINFO_H
#ifdef _WIN32
#pragma once
#endif
#include "disp_vertindex.h"
#include "bspfile.h"
#define NUM_POWERINFOS (MAX_MAP_DISP_POWER+1)
struct DispNodeInfo_t
{
enum
{
// Indicates if any children at all have triangles
CHILDREN_HAVE_TRIANGLES = 0x1
};
// Indicates which tesselation indices are associated with a node
unsigned short m_FirstTesselationIndex;
unsigned char m_Count;
unsigned char m_Flags;
};
// ------------------------------------------------------------------------ //
// CTesselateWindings are used to tell what order a node needs to visit
// vertices while tesselating.
// ------------------------------------------------------------------------ //
class CTesselateVert
{
public:
CTesselateVert( CVertIndex const &index, int iNode );
CVertIndex m_Index;
short m_iNode; // Which node this vert is a part of (-1 on left, right, up, and down).
};
class CTesselateWinding
{
public:
CTesselateVert *m_Verts;
short m_nVerts; // (includes the last vert)
};
class CVertDependency
{
public:
// Returns false if there is no dependency stored here.
bool IsValid() { return m_iVert.x != -1; }
public:
// The vert index is in the same power as the source displacement.
// It is also wrapped, so for example, on the middle of the right edge
// of a 3x3, it will have a dependency on the 3x3's root node (1,1), and it
// will have another (1,1) entry that references a neighbor.
CVertIndex m_iVert;
// This is -1 if the vert exists inside the source displacement.
// It is one of the NEIGHBOREDGE_ codes above if it reaches into a neighbor.
short m_iNeighbor;
};
// Precalculated data about displacement vertices.
class CVertInfo
{
public:
CVertInfo();
// These are the vertices that this vertex depends on (vertices that must be
// active for this vert to exist).
CVertDependency m_Dependencies[2];
// These are the vertices that have this vert in their m_Dependencies.
enum { NUM_REVERSE_DEPENDENCIES=4 };
CVertDependency m_ReverseDependencies[NUM_REVERSE_DEPENDENCIES];
short m_iNodeLevel; // -1 if this is not a node. Otherwise, the recursion level
// of this node (root node = 1).
CVertIndex m_iParent; // x=-1 if this is a not a node or if it's the root node.
};
class CTwoUShorts
{
public:
unsigned short m_Values[2];
};
class CFourVerts
{
public:
CVertIndex m_Verts[4];
};
// Used for referencing triangles in the fully-tesselated displacement by index.
class CTriInfo
{
public:
unsigned short m_Indices[3];
};
// Precalculated data for displacements of a certain power.
class CPowerInfo
{
public:
CPowerInfo(
CVertInfo *pVertInfo,
CFourVerts *pSideVerts,
CFourVerts *pChildVerts,
CFourVerts *pSideVertCorners,
CTwoUShorts *pErrorEdges,
CTriInfo *pTriInfos );
int GetPower() const { return m_Power; }
int GetSideLength() const { return m_SideLength; }
const CVertIndex& GetRootNode() const { return m_RootNode; }
int GetMidPoint() const { return m_MidPoint; } // Half the edge length.
// Get at the tri list.
int GetNumTriInfos() const { return m_nTriInfos; }
const CTriInfo* GetTriInfo( int i ) const { return &m_pTriInfos[i]; }
// Get the number of vertices in a displacement of this power.
int GetNumVerts() const { return m_MaxVerts; }
// Return a corner point index. Indexed by the CORNER_ defines.
const CVertIndex& GetCornerPointIndex( int iCorner ) const;
public:
CVertInfo *m_pVertInfo;
CFourVerts *m_pSideVerts; // The 4 side verts for each node.
CFourVerts *m_pChildVerts; // The 4 children for each node.
CFourVerts *m_pSideVertCorners;
CTwoUShorts *m_pErrorEdges; // These are the edges
// that are used to measure the screenspace
// error with respect to each vert.
CTriInfo *m_pTriInfos;
int m_nTriInfos;
int m_Power;
CVertIndex m_RootNode;
int m_SideLength;
int m_SideLengthM1; // Side length minus 1.
int m_MidPoint; // Side length / 2.
int m_MaxVerts; // m_SideLength * m_SideLength
int m_NodeCount; // total # of nodes, including children
// Precalculated increments if you're using a bit vector to represent nodes.
// Starting at level 0 of the tree, this stores the increment between the nodes at this
// level. Vectors holding node data are stored in preorder traversal, and these
// increments tell the number of elements between nodes at each level.
int m_NodeIndexIncrements[MAX_MAP_DISP_POWER];
CVertIndex m_EdgeStartVerts[4];
CVertIndex m_EdgeIncrements[4];
CVertIndex m_NeighborStartVerts[4][4]; // [side][orientation]
CVertIndex m_NeighborIncrements[4][4]; // [side][orientation]
private:
friend void InitPowerInfo( CPowerInfo *pInfo, int iMaxPower );
CVertIndex m_CornerPointIndices[4];
};
// ----------------------------------------------------------------------------- //
// Globals.
// ----------------------------------------------------------------------------- //
// Indexed by the TWINDING_ enums.
extern CTesselateWinding g_TWinding;
// ----------------------------------------------------------------------------- //
// Functions.
// ----------------------------------------------------------------------------- //
// Valid indices are MIN_MAP_DISP_POWER through (and including) MAX_MAP_DISP_POWER.
const CPowerInfo* GetPowerInfo( int iPower );
#endif // DISP_POWERINFO_H

206
public/disp_tesselate.h Normal file
View File

@ -0,0 +1,206 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef DISP_TESSELATE_H
#define DISP_TESSELATE_H
#ifdef _WIN32
#pragma once
#endif
#include "disp_powerinfo.h"
inline int InternalVertIndex( const CPowerInfo *pInfo, const CVertIndex &vert )
{
return vert.y * pInfo->m_SideLength + vert.x;
}
template< class TesselateHelper >
inline void InternalEndTriangle(
TesselateHelper *pHelper,
CVertIndex const &nodeIndex,
int &iCurTriVert )
{
// End our current triangle here.
Assert( iCurTriVert == 2 );
// Finish the triangle.
pHelper->m_TempIndices[2] = (unsigned short)InternalVertIndex( pHelper->m_pPowerInfo, nodeIndex );
pHelper->EndTriangle();
// Add on the last vertex to join to the next triangle.
pHelper->m_TempIndices[0] = pHelper->m_TempIndices[1];
iCurTriVert = 1;
}
//-----------------------------------------------------------------------------
// Tesselates a single node, doesn't deal with hierarchy
//-----------------------------------------------------------------------------
template< class TesselateHelper >
inline void TesselateDisplacementNode(
TesselateHelper *pHelper,
CVertIndex const &nodeIndex,
int iLevel,
int *pActiveChildren )
{
int iPower = pHelper->m_pPowerInfo->m_Power - iLevel;
int vertInc = 1 << (iPower - 1);
CTesselateWinding *pWinding = &g_TWinding;
// Starting at the bottom-left, wind clockwise picking up vertices and
// generating triangles.
int iCurTriVert = 0;
for( int iVert=0; iVert < pWinding->m_nVerts; iVert++ )
{
CVertIndex sideVert = BuildOffsetVertIndex( nodeIndex, pWinding->m_Verts[iVert].m_Index, vertInc );
int iVertNode = pWinding->m_Verts[iVert].m_iNode;
bool bNode = (iVertNode != -1) && pActiveChildren[iVertNode];
if( bNode )
{
if( iCurTriVert == 2 )
InternalEndTriangle( pHelper, nodeIndex, iCurTriVert );
iCurTriVert = 0;
}
else
{
int iVertBit = InternalVertIndex( pHelper->m_pPowerInfo, sideVert );
if( pHelper->m_pActiveVerts[iVertBit>>5] & (1 << (iVertBit & 31)) )
{
// Ok, add a vert here.
pHelper->m_TempIndices[iCurTriVert] = (unsigned short)InternalVertIndex( pHelper->m_pPowerInfo, sideVert );
iCurTriVert++;
if( iCurTriVert == 2 )
InternalEndTriangle( pHelper, nodeIndex, iCurTriVert );
}
}
}
}
//-----------------------------------------------------------------------------
// Tesselates in a *breadth first* fashion
//-----------------------------------------------------------------------------
template< class T >
inline void TesselateDisplacement_R(
T *pHelper,
const CVertIndex &nodeIndex,
int iNodeBitIndex,
int iLevel
)
{
// Here's the node info for our current node
Assert( iNodeBitIndex < pHelper->m_pPowerInfo->m_NodeCount );
DispNodeInfo_t& nodeInfo = pHelper->GetNodeInfo( iNodeBitIndex );
// Store off the current number of indices
int oldIndexCount = pHelper->m_nIndices;
// Go through each quadrant. If there is an active child node, recurse down.
int bActiveChildren[4];
if( iLevel >= pHelper->m_pPowerInfo->m_Power - 1 )
{
// This node has no children.
bActiveChildren[0] = bActiveChildren[1] = bActiveChildren[2] = bActiveChildren[3] = false;
}
else
{
int iNodeIndex = InternalVertIndex( pHelper->m_pPowerInfo, nodeIndex );
int iChildNodeBit = iNodeBitIndex + 1;
for( int iChild=0; iChild < 4; iChild++ )
{
CVertIndex const &childNode = pHelper->m_pPowerInfo->m_pChildVerts[iNodeIndex].m_Verts[iChild];
// Make sure we really can tesselate here (a smaller neighbor displacement could
// have inactivated certain edge verts.
int iVertBit = InternalVertIndex( pHelper->m_pPowerInfo, childNode );
bActiveChildren[iChild] = ( pHelper->m_pActiveVerts[iVertBit>>5] & (1 << (iVertBit & 31)) );
if( bActiveChildren[iChild] )
{
TesselateDisplacement_R( pHelper, childNode, iChildNodeBit, iLevel+1 );
}
else
{
// Make sure the triangle counts are cleared on this one because it may visit this
// node in GenerateDecalFragments_R if nodeInfo's CHILDREN_HAVE_TRIANGLES flag is set.
DispNodeInfo_t &childInfo = pHelper->GetNodeInfo( iChildNodeBit );
childInfo.m_Count = 0;
childInfo.m_Flags = 0;
}
iChildNodeBit += pHelper->m_pPowerInfo->m_NodeIndexIncrements[iLevel];
}
}
// Set the child field
if ( pHelper->m_nIndices != oldIndexCount )
{
nodeInfo.m_Flags = DispNodeInfo_t::CHILDREN_HAVE_TRIANGLES;
oldIndexCount = pHelper->m_nIndices;
}
else
{
nodeInfo.m_Flags = 0;
}
// Now tesselate the node itself...
TesselateDisplacementNode( pHelper, nodeIndex, iLevel, bActiveChildren );
// Now that we've tesselated, figure out how many indices we've added at this node
nodeInfo.m_Count = pHelper->m_nIndices - oldIndexCount;
nodeInfo.m_FirstTesselationIndex = oldIndexCount;
Assert( nodeInfo.m_Count % 3 == 0 );
}
class CBaseTesselateHelper
{
public:
// Functions your derived class must implement:
// void EndTriangle(); // (the 3 indices are in m_TempIndices).
// DispNodeInfo_t& GetNodeInfo( int iNodeBit );
// Set these before calling TesselateDisplacement.
uint32 *m_pActiveVerts; // These bits control the tesselation.
const CPowerInfo *m_pPowerInfo; // Lots of precalculated data about a displacement this size.
// Used internally by TesselateDisplacement.
int m_nIndices; // After calling TesselateDisplacement, this is set to the # of indices generated.
unsigned short m_TempIndices[6];
};
// This interface is shared betwixt VBSP and the engine. VBSP uses it to build the
// physics mesh and the engine uses it to render.
//
// To use this function, derive a class from CBaseTesselateHelper that supports the TesselateHelper functions.
template< class TesselateHelper >
inline void TesselateDisplacement( TesselateHelper *pHelper )
{
pHelper->m_nIndices = 0;
TesselateDisplacement_R<TesselateHelper>(
pHelper,
pHelper->m_pPowerInfo->m_RootNode,
0, // node bit indexing CDispDecal::m_NodeIntersects
0 );
}
#endif // DISP_TESSELATE_H

150
public/disp_vertindex.h Normal file
View File

@ -0,0 +1,150 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef DISP_VERTINDEX_H
#define DISP_VERTINDEX_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
// ------------------------------------------------------------------------ //
// Helper class used for indexing vertices in the 2D grid.
// ------------------------------------------------------------------------ //
class CVertIndex
{
public:
CVertIndex();
CVertIndex( short ix, short iy );
void Init( short ix, short iy );
short& operator[]( short i );
short const& operator[]( short i ) const;
void operator+=( CVertIndex const &other );
void operator-=( CVertIndex const &other );
CVertIndex operator+( CVertIndex const &other ) const;
CVertIndex operator-( CVertIndex const &other ) const;
void operator<<=( int shift );
void operator>>=( int shift );
bool operator==( CVertIndex const &other ) const;
bool operator!=( CVertIndex const &other ) const;
public:
short x, y;
};
// ------------------------------------------------------------------ //
// Helper functions.
// ------------------------------------------------------------------ //
inline CVertIndex BuildOffsetVertIndex(
CVertIndex const &nodeIndex,
CVertIndex const &offset,
int mul )
{
return CVertIndex( nodeIndex.x + offset.x * mul, nodeIndex.y + offset.y * mul );
}
// ------------------------------------------------------------------ //
// CVertIndex inlines.
// ------------------------------------------------------------------ //
inline CVertIndex::CVertIndex()
{
}
inline CVertIndex::CVertIndex( short ix, short iy )
{
x = ix;
y = iy;
}
inline void CVertIndex::Init( short ix, short iy )
{
x = ix;
y = iy;
}
inline short& CVertIndex::operator[]( short i )
{
Assert( i >= 0 && i <= 1 );
return ((short*)this)[i];
}
inline short const& CVertIndex::operator[]( short i ) const
{
Assert( i >= 0 && i <= 1 );
return ((short*)this)[i];
}
inline void CVertIndex::operator+=( CVertIndex const &other )
{
x += other.x;
y += other.y;
}
inline void CVertIndex::operator-=( CVertIndex const &other )
{
x -= other.x;
y -= other.y;
}
inline CVertIndex CVertIndex::operator+( CVertIndex const &other ) const
{
return CVertIndex( x + other.x, y + other.y );
}
inline CVertIndex CVertIndex::operator-( CVertIndex const &other ) const
{
return CVertIndex( x - other.x, y - other.y );
}
inline void CVertIndex::operator<<=( int shift )
{
x <<= shift;
y <<= shift;
}
inline void CVertIndex::operator>>=( int shift )
{
x >>= shift;
y >>= shift;
}
inline bool CVertIndex::operator==( CVertIndex const &other ) const
{
return x==other.x && y==other.y;
}
inline bool CVertIndex::operator!=( CVertIndex const &other ) const
{
return x!=other.x || y!=other.y;
}
#endif // DISP_VERTINDEX_H

1994
public/dispcoll.cpp Normal file

File diff suppressed because it is too large Load Diff

249
public/dispcoll.h Normal file
View File

@ -0,0 +1,249 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef DISPCOLL_H
#define DISPCOLL_H
#pragma once
#include "mathlib/vector.h"
class CCoreDispInfo;
//=============================================================================
//
// Displacement Collision Triangle Data
//
class CDispCollTri
{
public:
void Init( void );
inline void SetPoint( int index, Vector const& vert );
inline void SetPointNormal( int index, Vector const& normal );
void CalcPlane( void );
inline void SetIntersect( bool bIntersect );
inline bool IsIntersect( void );
Vector m_Points[3]; // polygon points
Vector m_PointNormals[3]; // polygon point normals
Vector m_Normal; // plane normal
float m_Distance; // plane distance
short m_ProjAxes[2]; // projection axes (2 minor axes)
bool m_bIntersect; // intersected triangle???
};
//=============================================================================
//
// Displacement Collision Node Data
//
class CDispCollNode
{
public:
CDispCollNode();
inline bool IsLeaf( void );
inline void SetBounds( Vector const &bMin, Vector const &bMax );
inline void GetBounds( Vector &bMin, Vector &bMax );
Vector m_Bounds[2]; // node minimum and maximum
bool m_bIsLeaf; // is the node a leaf? ( may have to make this an int for alignment!)
CDispCollTri m_Tris[2]; // two triangles contained in leaf node
};
//=============================================================================
//
// Displacement Collision Data
//
class CDispCollData
{
public:
Vector m_StartPos;
Vector m_EndPos;
Vector m_Extents;
float m_Fraction;
int m_Contents;
Vector m_Normal;
float m_Distance;
bool m_bOcclude;
};
// HACKHACK: JAY: Moved this out of CDispCollTree to be thread safe in vrad
enum { TRILIST_CACHE_SIZE = 128 };
class CDispCollTreeTempData
{
public:
//
// temps
//
int m_TriListCount;
CDispCollTri *m_ppTriList[TRILIST_CACHE_SIZE];
// collision tree node cache
float m_AABBDistances[6];
};
//=============================================================================
//
// Displacement Collision Tree
//
class CDispCollTree
{
public:
static const float COLLISION_EPSILON;
static const float ONE_MINUS_COLLISION_EPSILON;
//=========================================================================
//
// Creation/Destruction
//
CDispCollTree();
~CDispCollTree();
virtual bool Create( CCoreDispInfo *pDisp );
//=========================================================================
//
// Collision Functions
//
bool RayTest( CDispCollData *pData );
bool RayTestAllTris( CDispCollData *pData, int power );
bool AABBIntersect( CDispCollData *pData );
bool AABBSweep( CDispCollData *pData );
//=========================================================================
//
// Attrib Functions
//
inline void SetPower( int power );
inline int GetPower( void );
inline void SetCheckCount( int count );
inline int GetCheckCount( void );
inline void GetBounds( Vector& boundMin, Vector& boundMax );
protected:
int m_Power;
int m_NodeCount;
CDispCollNode *m_pNodes;
int m_CheckCount;
// collision tree node cache
Vector m_AABBNormals[6];
//=========================================================================
//
// Creation/Destruction
//
void InitAABBData( void );
void InitLeaves( CCoreDispInfo *pDisp );
void CreateNodes( CCoreDispInfo *pDisp );
void CreateNodes_r( CCoreDispInfo *pDisp, int nodeIndex, int termLevel );
void CalcBounds( CDispCollNode *pNode, int nodeIndex );
//=========================================================================
//
// Collision Functions
//
void CreatePlanesFromBounds( CDispCollTreeTempData *pTemp, Vector const &bbMin, Vector const &bbMax );
// void RayNodeTest_r( int nodeIndex, Vector &rayStart, Vector &rayEnd );
void RayNodeTest_r( CDispCollTreeTempData *pTemp, int nodeIndex, Vector rayStart, Vector rayEnd );
bool RayAABBTest( CDispCollTreeTempData *pTemp, Vector &rayStart, Vector &rayEnd );
bool RayTriListTest( CDispCollTreeTempData *pTemp, CDispCollData *pData );
bool RayTriTest( Vector const &rayStart, Vector const &rayDir, float const rayLength, CDispCollTri const *pTri, float *fraction );
void BuildTriList_r( CDispCollTreeTempData *pTemp, int nodeIndex, Vector &rayStart, Vector &rayEnd, Vector &extents, bool bIntersect );
bool IntersectAABBAABBTest( CDispCollTreeTempData *pTemp, const Vector &pos, const Vector &extents );
bool SweptAABBAABBTest( CDispCollTreeTempData *pTemp, const Vector &rayStart, const Vector &rayEnd, const Vector &extents );
bool CullTriList( CDispCollTreeTempData *pTemp, Vector &rayStart, Vector &rayEnd, Vector &extents, bool bIntersect );
bool SweptAABBTriTest( Vector &rayStart, Vector &rayEnd, Vector &extents, CDispCollTri const *pTri );
bool AABBTriIntersect( CDispCollTreeTempData *pTemp, CDispCollData *pData );
bool IntersectAABBTriTest( Vector &rayStart, Vector &extents, CDispCollTri const *pTri );
bool SweptAABBTriIntersect( Vector &rayStart, Vector &rayEnd, Vector &extents,
CDispCollTri const *pTri, Vector &plNormal, float *plDist,
float *fraction );
//=========================================================================
//
// Memory Functions
//
bool AllocNodes( int nodeCount );
void FreeNodes( void );
//=========================================================================
//
// Utility Functions
//
inline int CalcNodeCount( int power );
inline int GetParentNode( int nodeIndex );
inline int GetChildNode( int nodeIndex, int direction );
inline int GetNodeLevel( int nodeIndex );
int GetNodeIndexFromComponents( int x, int y );
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
inline void CDispCollTree::SetPower( int power )
{
m_Power = power;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
inline int CDispCollTree::GetPower( void )
{
return m_Power;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
inline void CDispCollTree::SetCheckCount( int count )
{
m_CheckCount = count;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
inline int CDispCollTree::GetCheckCount( void )
{
return m_CheckCount;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
inline void CDispCollTree::GetBounds( Vector& boundMin, Vector& boundMax )
{
boundMin[0] = m_pNodes[0].m_Bounds[0].x;
boundMin[1] = m_pNodes[0].m_Bounds[0].y;
boundMin[2] = m_pNodes[0].m_Bounds[0].z;
boundMax[0] = m_pNodes[0].m_Bounds[1].x;
boundMax[1] = m_pNodes[0].m_Bounds[1].y;
boundMax[2] = m_pNodes[0].m_Bounds[1].z;
}
#endif // DISPCOLL_H

1539
public/dispcoll_common.cpp Normal file

File diff suppressed because it is too large Load Diff

456
public/dispcoll_common.h Normal file
View File

@ -0,0 +1,456 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef DISPCOLL_COMMON_H
#define DISPCOLL_COMMON_H
#pragma once
#include "trace.h"
#include "builddisp.h"
#include "bitvec.h"
#ifdef ENGINE_DLL
#include "../engine/zone.h"
#endif
#ifdef ENGINE_DLL
template<typename T>
class CDispVector : public CUtlVector<T, CHunkMemory<T> >
{
};
#else
template<typename T>
class CDispVector : public CUtlVector<T, CUtlMemoryAligned<T,16> >
{
};
#endif
FORWARD_DECLARE_HANDLE( memhandle_t );
#define DISPCOLL_TREETRI_SIZE MAX_DISPTRIS
#define DISPCOLL_DIST_EPSILON 0.03125f
#define DISPCOLL_ROOTNODE_INDEX 0
#define DISPCOLL_INVALID_TRI -1
#define DISPCOLL_INVALID_FRAC -99999.9f
#define DISPCOLL_NORMAL_UNDEF 0xffff
extern double g_flDispCollSweepTimer;
extern double g_flDispCollIntersectTimer;
extern double g_flDispCollInCallTimer;
struct RayDispOutput_t
{
short ndxVerts[4]; // 3 verts and a pad
float u, v; // the u, v paramters (edgeU = v1 - v0, edgeV = v2 - v0)
float dist; // intersection distance
};
// Assumptions:
// Max patch is 17x17, therefore 9 bits needed to represent a triangle index
//
//=============================================================================
// Displacement Collision Triangle
class CDispCollTri
{
struct index_t
{
union
{
struct
{
unsigned short uiVert:9;
unsigned short uiMin:2;
unsigned short uiMax:2;
} m_Index;
unsigned short m_IndexDummy;
};
};
index_t m_TriData[3];
public:
unsigned short m_ucSignBits:3; // Plane test.
unsigned short m_ucPlaneType:3; // Axial test?
unsigned short m_uiFlags:5; // Uses 5-bits - maybe look into merging it with something?
Vector m_vecNormal; // Triangle normal (plane normal).
float m_flDist; // Triangle plane dist.
// Creation.
CDispCollTri();
void Init( void );
void CalcPlane( CDispVector<Vector> &m_aVerts );
void FindMinMax( CDispVector<Vector> &m_aVerts );
// Triangle data.
inline void SetVert( int iPos, int iVert ) { Assert( ( iPos >= 0 ) && ( iPos < 3 ) ); Assert( ( iVert >= 0 ) && ( iVert < ( 1 << 9 ) ) ); m_TriData[iPos].m_Index.uiVert = iVert; }
inline int GetVert( int iPos ) const { Assert( ( iPos >= 0 ) && ( iPos < 3 ) ); return m_TriData[iPos].m_Index.uiVert; }
inline void SetMin( int iAxis, int iMin ) { Assert( ( iAxis >= 0 ) && ( iAxis < 3 ) ); Assert( ( iMin >= 0 ) && ( iMin < 3 ) ); m_TriData[iAxis].m_Index.uiMin = iMin; }
inline int GetMin( int iAxis ) const { Assert( ( iAxis >= 0 ) && ( iAxis < 3 ) ); return m_TriData[iAxis].m_Index.uiMin; }
inline void SetMax( int iAxis, int iMax ) { Assert( ( iAxis >= 0 ) && ( iAxis < 3 ) ); Assert( ( iMax >= 0 ) && ( iMax < 3 ) ); m_TriData[iAxis].m_Index.uiMax = iMax; }
inline int GetMax( int iAxis ) const { Assert( ( iAxis >= 0 ) && ( iAxis < 3 ) ); return m_TriData[iAxis].m_Index.uiMax; }
};
//=============================================================================
// Helper
class CDispCollHelper
{
public:
float m_flStartFrac;
float m_flEndFrac;
Vector m_vecImpactNormal;
float m_flImpactDist;
};
//=============================================================================
// Cache
#pragma pack(1)
class CDispCollTriCache
{
public:
unsigned short m_iCrossX[3];
unsigned short m_iCrossY[3];
unsigned short m_iCrossZ[3];
};
#pragma pack()
#include "mathlib/ssemath.h"
class CDispCollNode
{
public:
FourVectors m_mins;
FourVectors m_maxs;
};
class CDispCollLeaf
{
public:
short m_tris[2];
};
// a power 4 displacement can have 341 nodes, pad out to 344 for 16-byte alignment
const int MAX_DISP_AABB_NODES = 341;
const int MAX_AABB_LIST = 344;
struct rayleaflist_t
{
FourVectors rayStart;
FourVectors rayExtents;
FourVectors invDelta;
int nodeList[MAX_AABB_LIST];
int maxIndex;
};
//=============================================================================
//
// Displacement Collision Tree Data
//
class CDispCollTree
{
public:
// Creation/Destruction.
CDispCollTree();
~CDispCollTree();
virtual bool Create( CCoreDispInfo *pDisp );
// Raycasts.
// NOTE: These assume you've precalculated invDelta as well as culled to the bounds of this disp
bool AABBTree_Ray( const Ray_t &ray, const Vector &invDelta, CBaseTrace *pTrace, bool bSide = true );
bool AABBTree_Ray( const Ray_t &ray, const Vector &invDelta, RayDispOutput_t &output );
// NOTE: Lower perf helper function, should not be used in the game runtime
bool AABBTree_Ray( const Ray_t &ray, RayDispOutput_t &output );
// Hull Sweeps.
// NOTE: These assume you've precalculated invDelta as well as culled to the bounds of this disp
bool AABBTree_SweepAABB( const Ray_t &ray, const Vector &invDelta, CBaseTrace *pTrace );
// Hull Intersection.
bool AABBTree_IntersectAABB( const Vector &absMins, const Vector &absMaxs );
// Point/Box vs. Bounds.
bool PointInBounds( Vector const &vecBoxCenter, Vector const &vecBoxMin, Vector const &vecBoxMax, bool bPoint );
// Utility.
inline void SetPower( int power ) { m_nPower = power; }
inline int GetPower( void ) { return m_nPower; }
inline int GetFlags( void ) { return m_nFlags; }
inline void SetFlags( int nFlags ) { m_nFlags = nFlags; }
inline bool CheckFlags( int nFlags ) { return ( ( nFlags & GetFlags() ) != 0 ) ? true : false; }
inline int GetWidth( void ) { return ( ( 1 << m_nPower ) + 1 ); }
inline int GetHeight( void ) { return ( ( 1 << m_nPower ) + 1 ); }
inline int GetSize( void ) { return ( ( 1 << m_nPower ) + 1 ) * ( ( 1 << m_nPower ) + 1 ); }
inline int GetTriSize( void ) { return ( ( 1 << m_nPower ) * ( 1 << m_nPower ) * 2 ); }
// inline void SetTriFlags( short iTri, unsigned short nFlags ) { m_aTris[iTri].m_uiFlags = nFlags; }
inline void GetStabDirection( Vector &vecDir ) { vecDir = m_vecStabDir; }
inline void GetBounds( Vector &vecBoxMin, Vector &vecBoxMax ) { vecBoxMin = m_mins; vecBoxMax = m_maxs; }
inline int GetContents( void ) { return m_nContents; }
inline void SetSurfaceProps( int iProp, short nSurfProp ) { Assert( ( iProp >= 0 ) && ( iProp < 2 ) ); m_nSurfaceProps[iProp] = nSurfProp; }
inline short GetSurfaceProps( int iProp ) { return m_nSurfaceProps[iProp]; }
inline unsigned int GetMemorySize( void ) { return m_nSize; }
inline unsigned int GetCacheMemorySize( void ) { return ( m_aTrisCache.Count() * sizeof(CDispCollTriCache) + m_aEdgePlanes.Count() * sizeof(Vector) ); }
inline bool IsCached( void ) { return m_aTrisCache.Count() == m_aTris.Count(); }
void GetVirtualMeshList( struct virtualmeshlist_t *pList );
int AABBTree_GetTrisInSphere( const Vector &center, float radius, unsigned short *pIndexOut, int indexMax );
public:
inline int Nodes_GetChild( int iNode, int nDirection );
inline int Nodes_CalcCount( int nPower );
inline int Nodes_GetParent( int iNode );
inline int Nodes_GetLevel( int iNode );
inline int Nodes_GetIndexFromComponents( int x, int y );
void LockCache();
void UnlockCache();
void Cache( void );
void Uncache() { m_aTrisCache.Purge(); m_aEdgePlanes.Purge(); }
#ifdef ENGINE_DLL
// Data manager methods
static size_t EstimatedSize( CDispCollTree *pTree )
{
return pTree->GetCacheMemorySize();
}
static CDispCollTree *CreateResource( CDispCollTree *pTree )
{
// Created ahead of time
return pTree;
}
bool GetData()
{
return IsCached();
}
size_t Size()
{
return GetCacheMemorySize();
}
void DestroyResource()
{
Uncache();
m_hCache = NULL;
}
#endif
protected:
bool AABBTree_Create( CCoreDispInfo *pDisp );
void AABBTree_CopyDispData( CCoreDispInfo *pDisp );
void AABBTree_CreateLeafs( void );
void AABBTree_GenerateBoxes_r( int nodeIndex, Vector *pMins, Vector *pMaxs );
void AABBTree_CalcBounds( void );
int AABBTree_BuildTreeTrisInSphere_r( const Vector &center, float radius, int iNode, unsigned short *pIndexOut, unsigned short indexMax );
void AABBTree_TreeTrisRayTest( const Ray_t &ray, const Vector &vecInvDelta, int iNode, CBaseTrace *pTrace, bool bSide, CDispCollTri **pImpactTri );
void AABBTree_TreeTrisRayBarycentricTest( const Ray_t &ray, const Vector &vecInvDelta, int iNode, RayDispOutput_t &output, CDispCollTri **pImpactTri );
int FORCEINLINE BuildRayLeafList( int iNode, rayleaflist_t &list );
struct AABBTree_TreeTrisSweepTest_Args_t
{
AABBTree_TreeTrisSweepTest_Args_t( const Ray_t &ray, const Vector &vecInvDelta, const Vector &rayDir, CBaseTrace *pTrace )
: ray( ray ), vecInvDelta( vecInvDelta ), rayDir( rayDir ), pTrace( pTrace ) {}
const Ray_t &ray;
const Vector &vecInvDelta;
const Vector &rayDir;
CBaseTrace *pTrace;
};
protected:
void SweepAABBTriIntersect( const Ray_t &ray, const Vector &rayDir, int iTri, CDispCollTri *pTri, CBaseTrace *pTrace );
void Cache_Create( CDispCollTri *pTri, int iTri ); // Testing!
bool Cache_EdgeCrossAxisX( const Vector &vecEdge, const Vector &vecOnEdge, const Vector &vecOffEdge, CDispCollTri *pTri, unsigned short &iPlane );
bool Cache_EdgeCrossAxisY( const Vector &vecEdge, const Vector &vecOnEdge, const Vector &vecOffEdge, CDispCollTri *pTri, unsigned short &iPlane );
bool Cache_EdgeCrossAxisZ( const Vector &vecEdge, const Vector &vecOnEdge, const Vector &vecOffEdge, CDispCollTri *pTri, unsigned short &iPlane );
inline bool FacePlane( const Ray_t &ray, const Vector &rayDir, CDispCollTri *pTri, CDispCollHelper *pHelper );
bool FORCEINLINE AxisPlanesXYZ( const Ray_t &ray, CDispCollTri *pTri, CDispCollHelper *pHelper );
inline bool EdgeCrossAxisX( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper );
inline bool EdgeCrossAxisY( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper );
inline bool EdgeCrossAxisZ( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper );
bool ResolveRayPlaneIntersect( float flStart, float flEnd, const Vector &vecNormal, float flDist, CDispCollHelper *pHelper );
template <int AXIS> bool FORCEINLINE TestOneAxisPlaneMin( const Ray_t &ray, CDispCollTri *pTri );
template <int AXIS> bool FORCEINLINE TestOneAxisPlaneMax( const Ray_t &ray, CDispCollTri *pTri );
template <int AXIS> bool EdgeCrossAxis( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper );
// Utility
inline void CalcClosestBoxPoint( const Vector &vecPlaneNormal, const Vector &vecBoxStart, const Vector &vecBoxExtents, Vector &vecBoxPoint );
inline void CalcClosestExtents( const Vector &vecPlaneNormal, const Vector &vecBoxExtents, Vector &vecBoxPoint );
int AddPlane( const Vector &vecNormal );
bool FORCEINLINE IsLeafNode(int iNode);
public:
Vector m_mins; // Bounding box of the displacement surface and base face
int m_iCounter;
Vector m_maxs; // Bounding box of the displacement surface and base face
protected:
int m_nContents; // The displacement surface "contents" (solid, etc...)
#ifdef ENGINE_DLL
memhandle_t m_hCache;
#endif
int m_nPower; // Size of the displacement ( 2^power + 1 )
int m_nFlags;
Vector m_vecSurfPoints[4]; // Base surface points.
// Collision data.
Vector m_vecStabDir; // Direction to stab for this displacement surface (is the base face normal)
short m_nSurfaceProps[2]; // Surface properties (save off from texdata for impact responses)
protected:
CDispVector<Vector> m_aVerts; // Displacement verts.
CDispVector<CDispCollTri> m_aTris; // Displacement triangles.
CDispVector<CDispCollNode> m_nodes; // Nodes.
CDispVector<CDispCollLeaf> m_leaves; // Leaves.
// Cache
CUtlVector<CDispCollTriCache> m_aTrisCache;
CUtlVector<Vector> m_aEdgePlanes;
CDispCollHelper m_Helper;
unsigned int m_nSize;
};
FORCEINLINE bool CDispCollTree::IsLeafNode(int iNode)
{
return iNode >= m_nodes.Count() ? true : false;
}
//-----------------------------------------------------------------------------
// Purpose: get the child node index given the current node index and direction
// of the child (1 of 4)
// Input: iNode - current node index
// nDirection - direction of the child ( [0...3] - SW, SE, NW, NE )
// Output: int - the index of the child node
//-----------------------------------------------------------------------------
inline int CDispCollTree::Nodes_GetChild( int iNode, int nDirection )
{
// node range [0...m_NodeCount)
Assert( iNode >= 0 );
Assert( iNode < m_nodes.Count() );
// ( node index * 4 ) + ( direction + 1 )
return ( ( iNode << 2 ) + ( nDirection + 1 ) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
inline int CDispCollTree::Nodes_CalcCount( int nPower )
{
Assert( nPower >= 1 );
Assert( nPower <= 4 );
return ( ( 1 << ( ( nPower + 1 ) << 1 ) ) / 3 );
}
//-----------------------------------------------------------------------------
// Purpose: get the parent node index given the current node
// Input: iNode - current node index
// Output: int - the index of the parent node
//-----------------------------------------------------------------------------
inline int CDispCollTree::Nodes_GetParent( int iNode )
{
// node range [0...m_NodeCount)
Assert( iNode >= 0 );
Assert( iNode < m_nodes.Count() );
// ( node index - 1 ) / 4
return ( ( iNode - 1 ) >> 2 );
}
//-----------------------------------------------------------------------------
// Purpose:
// TODO: should make this a function - not a hardcoded set of statements!!!
//-----------------------------------------------------------------------------
inline int CDispCollTree::Nodes_GetLevel( int iNode )
{
// node range [0...m_NodeCount)
Assert( iNode >= 0 );
Assert( iNode < m_nodes.Count() );
// level = 2^n + 1
if ( iNode == 0 ) { return 1; }
if ( iNode < 5 ) { return 2; }
if ( iNode < 21 ) { return 3; }
if ( iNode < 85 ) { return 4; }
if ( iNode < 341 ) { return 5; }
return -1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
inline int CDispCollTree::Nodes_GetIndexFromComponents( int x, int y )
{
int nIndex = 0;
// Interleave bits from the x and y values to create the index
int iShift;
for( iShift = 0; x != 0; iShift += 2, x >>= 1 )
{
nIndex |= ( x & 1 ) << iShift;
}
for( iShift = 1; y != 0; iShift += 2, y >>= 1 )
{
nIndex |= ( y & 1 ) << iShift;
}
return nIndex;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
inline void CDispCollTree::CalcClosestBoxPoint( const Vector &vecPlaneNormal, const Vector &vecBoxStart,
const Vector &vecBoxExtents, Vector &vecBoxPoint )
{
vecBoxPoint = vecBoxStart;
( vecPlaneNormal[0] < 0.0f ) ? vecBoxPoint[0] += vecBoxExtents[0] : vecBoxPoint[0] -= vecBoxExtents[0];
( vecPlaneNormal[1] < 0.0f ) ? vecBoxPoint[1] += vecBoxExtents[1] : vecBoxPoint[1] -= vecBoxExtents[1];
( vecPlaneNormal[2] < 0.0f ) ? vecBoxPoint[2] += vecBoxExtents[2] : vecBoxPoint[2] -= vecBoxExtents[2];
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
inline void CDispCollTree::CalcClosestExtents( const Vector &vecPlaneNormal, const Vector &vecBoxExtents,
Vector &vecBoxPoint )
{
( vecPlaneNormal[0] < 0.0f ) ? vecBoxPoint[0] = vecBoxExtents[0] : vecBoxPoint[0] = -vecBoxExtents[0];
( vecPlaneNormal[1] < 0.0f ) ? vecBoxPoint[1] = vecBoxExtents[1] : vecBoxPoint[1] = -vecBoxExtents[1];
( vecPlaneNormal[2] < 0.0f ) ? vecBoxPoint[2] = vecBoxExtents[2] : vecBoxPoint[2] = -vecBoxExtents[2];
}
//=============================================================================
// Global Helper Functions
CDispCollTree *DispCollTrees_Alloc( int count );
void DispCollTrees_Free( CDispCollTree *pTrees );
#endif // DISPCOLL_COMMON_H

84
public/dlight.h Normal file
View File

@ -0,0 +1,84 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#if !defined ( DLIGHTH )
#define DLIGHTH
#ifdef _WIN32
#pragma once
#endif
#include "mathlib/vector.h"
//-----------------------------------------------------------------------------
// Dynamic light structure
//-----------------------------------------------------------------------------
enum
{
DLIGHT_NO_WORLD_ILLUMINATION = 0x1,
DLIGHT_NO_MODEL_ILLUMINATION = 0x2,
// NOTE: These two features are used to dynamically tweak the alpha on displacements
// which is a special effect for selecting which texture to use. If
// we ever change how alpha is stored for displacements, we'll have to kill this feature
DLIGHT_ADD_DISPLACEMENT_ALPHA = 0x4,
DLIGHT_SUBTRACT_DISPLACEMENT_ALPHA = 0x8,
DLIGHT_DISPLACEMENT_MASK = (DLIGHT_ADD_DISPLACEMENT_ALPHA | DLIGHT_SUBTRACT_DISPLACEMENT_ALPHA),
};
// This is the lighting value that is used to determine when something can be
// culle from lighting because it is close enough to black to be virtually black.
//#define MIN_LIGHTING_VALUE (1.0f/256.0f)
// This is the broken value of MIN_LIGHTING_VALUE that we have to take into consideration
// to make sure that the lighting for dlights look the same as they did in HL2.
// We'll use the real MIN_LIGHTING_VALUE above to calculate larger radii for dynamic
// light sources.
//#define HL2_BROKEN_MIN_LIGHTING_VALUE (20.0f/256.0f)
struct dlight_t
{
int flags;
Vector origin;
float radius;
ColorRGBExp32 color; // Light color with exponent
float die; // stop lighting after this time
float decay; // drop this each second
float minlight; // don't add when contributing less
int key;
int style; // lightstyle
// For spotlights. Use m_OuterAngle == 0 for point lights
Vector m_Direction; // center of the light cone
float m_InnerAngle;
float m_OuterAngle;
// see comments above about HL2_BROKEN_MIN_LIGHTING_VALUE and MIN_LIGHTING_VALUE
// THIS SHOULD ONLY GET CALLED FROM THE ENGINE
float GetRadius() const
{
// return FastSqrt( radius * radius * ( HL2_BROKEN_MIN_LIGHTING_VALUE / MIN_LIGHTING_VALUE ) );
return radius;
}
// see comments above about HL2_BROKEN_MIN_LIGHTING_VALUE and MIN_LIGHTING_VALUE
// THIS SHOULD ONLY GET CALLED FROM THE ENGINE
float GetRadiusSquared() const
{
// return radius * radius * ( HL2_BROKEN_MIN_LIGHTING_VALUE / MIN_LIGHTING_VALUE );
return radius * radius;
}
// THIS SHOULD ONLY GET CALLED FROM THE ENGINE
float IsRadiusGreaterThanZero() const
{
// don't bother calculating the new radius if you just want to know if it is greater than zero.
return radius > 0.0f;
}
};
#endif

View File

@ -0,0 +1,47 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// Main header file for the serializers DLL
//
//=============================================================================
#ifndef IDMSERIALIZERS_H
#define IDMSERIALIZERS_H
#ifdef _WIN32
#pragma once
#endif
#include "appframework/IAppSystem.h"
//-----------------------------------------------------------------------------
// Interface
//-----------------------------------------------------------------------------
class IDmSerializers : public IAppSystem
{
};
//-----------------------------------------------------------------------------
// Used only by applications to hook in DmSerializers
//-----------------------------------------------------------------------------
#define DMSERIALIZERS_INTERFACE_VERSION "VDmSerializers001"
//-----------------------------------------------------------------------------
// Singleton
//-----------------------------------------------------------------------------
extern IDmSerializers *g_pDmSerializers;
#endif // DMSERIALIZERS_H

View File

@ -0,0 +1,183 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef DMXATTRIBUTE_H
#define DMXATTRIBUTE_H
#ifdef _WIN32
#pragma once
#endif
#include "datamodel/dmattributetypes.h"
#include "tier1/utlvector.h"
#include "tier1/utlrbtree.h"
#include "tier1/utlsymbol.h"
#include "tier1/mempool.h"
#include "dmxloader/dmxloader.h"
//-----------------------------------------------------------------------------
// Forward declarations:
//-----------------------------------------------------------------------------
class CDmxElement;
//-----------------------------------------------------------------------------
// Attribute info, modified for use in mod code
//-----------------------------------------------------------------------------
DECLARE_ATTRIBUTE_TYPE( CDmxElement*, AT_ELEMENT, "element", value = 0; )
DECLARE_ATTRIBUTE_ARRAY_TYPE( CDmxElement*, AT_ELEMENT_ARRAY, "element_array" )
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CDmxAttribute
{
DECLARE_DMX_ALLOCATOR( );
public:
// Returns attribute name and type
DmAttributeType_t GetType() const;
const char *GetTypeString() const;
template< class T > bool IsA() const;
// Returns the name. NOTE: The utlsymbol
// can be turned into a string by using g_pDataModel->String();
const char *GetName() const;
CUtlSymbol GetNameSymbol() const;
void SetName( const char *pName );
// Gets values
template< class T > const T& GetValue( ) const;
template< class T > const CUtlVector< T >& GetArray( ) const;
const char *GetValueString() const;
// Sets values (+ type)
template< class T > void SetValue( const T& value );
void SetValue( const char *pString );
void SetValue( const void *pBuffer, size_t nLen );
void SetValue( const CDmxAttribute *pAttribute );
// Method to set values in an array (just directly operate on the array)
// NOTE: This will create a new array of the appropriate type if
// the type doesn't match the current type
template< class T > CUtlVector< T >& GetArrayForEdit();
// Sets the attribute to its default value based on its type
void SetToDefaultValue();
// Convert to and from string
void SetValueFromString( const char *pValue );
const char *GetValueAsString( char *pBuffer, size_t nBufLen ) const;
// Gets the size of an array, returns 0 if it's not an array type
int GetArrayCount() const;
// Read from file
bool Unserialize( DmAttributeType_t type, CUtlBuffer &buf );
bool UnserializeElement( DmAttributeType_t type, CUtlBuffer &buf );
bool Serialize( CUtlBuffer &buf ) const;
bool SerializeElement( int nIndex, CUtlBuffer &buf ) const;
bool SerializesOnMultipleLines() const;
// Returns the size of the variables storing the various attribute types
static int AttributeDataSize( DmAttributeType_t type );
private:
CDmxAttribute( const char *pAttributeName );
CDmxAttribute( CUtlSymbol attributeName );
~CDmxAttribute();
// Allocate, free memory for data
void AllocateDataMemory( DmAttributeType_t type );
void FreeDataMemory( );
// Untyped method for setting used by unpack
void SetValue( DmAttributeType_t type, const void *pSrc, int nLen );
DmAttributeType_t m_Type;
CUtlSymbol m_Name;
void *m_pData;
static CUtlSymbolTableMT s_AttributeNameSymbols;
friend class CDmxElement;
};
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline DmAttributeType_t CDmxAttribute::GetType() const
{
return m_Type;
}
template< class T > inline bool CDmxAttribute::IsA() const
{
return GetType() == CDmAttributeInfo< T >::ATTRIBUTE_TYPE;
}
inline CUtlSymbol CDmxAttribute::GetNameSymbol() const
{
return m_Name;
}
//-----------------------------------------------------------------------------
// Sets a value in the attribute
//-----------------------------------------------------------------------------
template< class T > void CDmxAttribute::SetValue( const T& value )
{
AllocateDataMemory( CDmAttributeInfo<T>::AttributeType() );
CopyConstruct( (T*)m_pData, value );
}
//-----------------------------------------------------------------------------
// Returns data in the attribute
//-----------------------------------------------------------------------------
inline const char *CDmxAttribute::GetValueString() const
{
if ( m_Type == AT_STRING )
return *(CUtlString*)m_pData;
return "";
}
template< class T >
inline const T& CDmxAttribute::GetValue( ) const
{
if ( CDmAttributeInfo<T>::AttributeType() == m_Type )
return *(T*)m_pData;
static T defaultValue;
CDmAttributeInfo<T>::SetDefaultValue( defaultValue );
return defaultValue;
}
template< class T >
inline const CUtlVector< T >& CDmxAttribute::GetArray( ) const
{
if ( CDmAttributeInfo< CUtlVector< T > >::AttributeType() == m_Type )
return *( CUtlVector< T > *)m_pData;
static CUtlVector<T> defaultArray;
return defaultArray;
}
template< class T >
inline CUtlVector< T >& CDmxAttribute::GetArrayForEdit( )
{
if ( CDmAttributeInfo< CUtlVector< T > >::AttributeType() == m_Type )
return *( CUtlVector< T > *)m_pData;
AllocateDataMemory( CDmAttributeInfo< CUtlVector< T > >::AttributeType() );
Construct( (CUtlVector<T>*)m_pData );
return *(CUtlVector< T > *)m_pData;
}
#endif // DMXATTRIBUTE_H

View File

@ -0,0 +1,310 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef DMXELEMENT_H
#define DMXELEMENT_H
#ifdef _WIN32
#pragma once
#endif
#include "datamodel/dmattributetypes.h"
#include "tier1/utlvector.h"
#include "tier1/utlrbtree.h"
#include "tier1/utlsymbol.h"
#include "tier1/mempool.h"
#include "tier1/UtlSortVector.h"
#include "dmxloader/dmxattribute.h"
//-----------------------------------------------------------------------------
// Sort functor class for attributes
//-----------------------------------------------------------------------------
class CDmxAttributeLess
{
public:
bool Less( const CDmxAttribute * pAttribute1, const CDmxAttribute *pAttribute2, void *pContext )
{
return pAttribute1->GetNameSymbol() < pAttribute2->GetNameSymbol();
}
};
//-----------------------------------------------------------------------------
// Used to unpack elements into a structure. Does not recurse
// Also does not work with arrays.
//-----------------------------------------------------------------------------
struct DmxElementUnpackStructure_t
{
const char *m_pAttributeName;
const char *m_pDefaultString;
DmAttributeType_t m_AttributeType;
int m_nOffset;
int m_nSize;
const void *m_pUserData; // If you want to associate some app-specific data with each field
};
#define DECLARE_DMXELEMENT_UNPACK() \
template <typename T> friend DmxElementUnpackStructure_t *DmxElementUnpackInit(T *);
#define BEGIN_DMXELEMENT_UNPACK( _structName ) \
template <typename T> DmxElementUnpackStructure_t *DmxElementUnpackInit(T *); \
template <> DmxElementUnpackStructure_t *DmxElementUnpackInit<_structName>( _structName * ); \
namespace _structName##_UnpackInit \
{ \
static DmxElementUnpackStructure_t *s_pUnpack = DmxElementUnpackInit( (_structName *)NULL ); \
} \
\
template <> DmxElementUnpackStructure_t *DmxElementUnpackInit<_structName>( _structName * ) \
{ \
typedef _structName DestStructType_t; \
static DmxElementUnpackStructure_t unpack[] = \
{ \
#define DMXELEMENT_UNPACK_FLTX4( _attributeName, _defaultString, _varName ) \
{ _attributeName, _defaultString, CDmAttributeInfo<float>::AttributeType(), offsetof( DestStructType_t, _varName ), sizeof( fltx4 ), NULL },
#define DMXELEMENT_UNPACK_FIELD( _attributeName, _defaultString, _type, _varName ) \
{ _attributeName, _defaultString, CDmAttributeInfo<_type>::AttributeType(), offsetof( DestStructType_t, _varName ), sizeof( ((DestStructType_t *)0)->_varName), NULL },
#define DMXELEMENT_UNPACK_FIELD_STRING( _attributeName, _defaultString, _varName ) \
{ _attributeName, _defaultString, AT_STRING, offsetof( DestStructType_t, _varName ), sizeof( ((DestStructType_t *)0)->_varName), NULL },
#define DMXELEMENT_UNPACK_FIELD_USERDATA( _attributeName, _defaultString, _type, _varName, _userData ) \
{ _attributeName, _defaultString, CDmAttributeInfo<_type>::AttributeType(), offsetof( DestStructType_t, _varName ), sizeof( ((DestStructType_t *)0)->_varName), _userData },
#define DMXELEMENT_UNPACK_FIELD_STRING_USERDATA( _attributeName, _defaultString, _varName, _userData ) \
{ _attributeName, _defaultString, AT_STRING, offsetof( DestStructType_t, _varName ), sizeof( ((DestStructType_t *)0)->_varName), _userData },
#define END_DMXELEMENT_UNPACK( _structName, _varName ) \
{ NULL, NULL, AT_UNKNOWN, 0, 0, NULL } \
}; \
return unpack; \
} \
DmxElementUnpackStructure_t *_varName = _structName##_UnpackInit::s_pUnpack;
#define END_DMXELEMENT_UNPACK_TEMPLATE( _structName, _varName ) \
{ NULL, NULL, AT_UNKNOWN, 0, 0, NULL } \
}; \
return unpack; \
} \
template<> DmxElementUnpackStructure_t *_varName = _structName##_UnpackInit::s_pUnpack;
//-----------------------------------------------------------------------------
// Element used to read dmx files from mod code. Similar to keyvalues.
//-----------------------------------------------------------------------------
class CDmxElement
{
DECLARE_DMX_ALLOCATOR( );
public:
bool HasAttribute( const char *pAttributeName ) const;
CDmxAttribute *GetAttribute( const char *pAttributeName );
const CDmxAttribute *GetAttribute( const char *pAttributeName ) const;
int AttributeCount() const;
CDmxAttribute *GetAttribute( int nIndex );
const CDmxAttribute *GetAttribute( int nIndex ) const;
CUtlSymbol GetType() const;
const char* GetTypeString() const;
const char* GetName() const;
const DmObjectId_t &GetId() const;
// Add+remove+rename can only occur during lock
// NOTE: AddAttribute will find or add; returning an existing attribute if
// one with the appropriate name exists
void LockForChanges( bool bLock );
CDmxAttribute *AddAttribute( const char *pAttributeName );
void RemoveAttribute( const char *pAttributeName );
void RemoveAttributeByPtr( CDmxAttribute *pAttribute );
void RemoveAllAttributes();
void RenameAttribute( const char *pAttributeName, const char *pNewName );
// Simple methods to read attributes
const char *GetValueString( const char *pAttributeName ) const;
template< class T > const T& GetValue( const char *pAttributeName ) const;
template< class T > const T& GetValue( const char *pAttributeName, const T& defaultValue ) const;
template< class T > const CUtlVector<T>& GetArray( const char *pAttributeName ) const;
template< class T > const CUtlVector<T>& GetArray( const char *pAttributeName, const CUtlVector<T>& defaultValue ) const;
// Set methods
CDmxAttribute* SetValue( const char *pAttributeName, const char *pString );
CDmxAttribute* SetValue( const char *pAttributeName, void *pBuffer, int nLen );
template< class T > CDmxAttribute* SetValue( const char *pAttributeName, const T& value );
// Method to unpack data into a structure
void UnpackIntoStructure( void *pData, size_t DataSizeInBytes, const DmxElementUnpackStructure_t *pUnpack ) const;
// Creates attributes based on the unpack structure
template <typename T>
void AddAttributesFromStructure( const T *pData, const DmxElementUnpackStructure_t *pUnpack )
{
AddAttributesFromStructure_Internal( pData, sizeof(T), pUnpack );
}
private:
void AddAttributesFromStructure_Internal( const void *pData, size_t byteCount, const DmxElementUnpackStructure_t *pUnpack );
typedef CUtlSortVector< CDmxAttribute*, CDmxAttributeLess > AttributeList_t;
CDmxElement( const char *pType );
~CDmxElement();
// Removes all elements recursively
void RemoveAllElementsRecursive();
// Adds elements to delete to the deletion list
void AddElementsToDelete( CUtlVector< CDmxElement * >& elementsToDelete );
// Sorts the vector when a change has occurred
void Resort( ) const;
// Finds an attribute by name
int FindAttribute( const char *pAttributeName ) const;
int FindAttribute( CUtlSymbol attributeName ) const;
// Sets the object id
void SetId( const DmObjectId_t &id );
// Are we locked?
bool IsLocked() const;
AttributeList_t m_Attributes;
DmObjectId_t m_Id; // We need this strictly because we support serialization
CUtlSymbol m_Type;
char m_nLockCount;
mutable bool m_bResortNeeded : 1;
bool m_bIsMarkedForDeletion : 1;
static CUtlSymbolTableMT s_TypeSymbols;
friend class CDmxSerializer;
friend class CDmxSerializerKeyValues2;
friend void CleanupDMX( CDmxElement* pElement );
friend CDmxElement* CreateDmxElement( const char *pType );
};
//-----------------------------------------------------------------------------
// inline methods
//-----------------------------------------------------------------------------
// Are we locked?
inline bool CDmxElement::IsLocked() const
{
return m_nLockCount > 0;
}
inline const char *CDmxElement::GetValueString( const char *pAttributeName ) const
{
const CDmxAttribute* pAttribute = GetAttribute( pAttributeName );
if ( pAttribute )
return pAttribute->GetValueString();
return "";
}
template< class T >
inline const T& CDmxElement::GetValue( const char *pAttributeName ) const
{
const CDmxAttribute* pAttribute = GetAttribute( pAttributeName );
if ( pAttribute )
return pAttribute->GetValue<T>();
static T defaultValue;
CDmAttributeInfo<T>::SetDefaultValue( defaultValue );
return defaultValue;
}
template< class T >
inline const T& CDmxElement::GetValue( const char *pAttributeName, const T& defaultValue ) const
{
const CDmxAttribute* pAttribute = GetAttribute( pAttributeName );
if ( pAttribute )
return pAttribute->GetValue<T>();
return defaultValue;
}
template< class T >
inline const CUtlVector<T>& CDmxElement::GetArray( const char *pAttributeName ) const
{
const CDmxAttribute* pAttribute = GetAttribute( pAttributeName );
if ( pAttribute )
return pAttribute->GetArray<T>();
static CUtlVector<T> defaultValue;
return defaultValue;
}
template< class T >
inline const CUtlVector<T>& CDmxElement::GetArray( const char *pAttributeName, const CUtlVector<T>& defaultValue ) const
{
const CDmxAttribute* pAttribute = GetAttribute( pAttributeName );
if ( pAttribute )
return pAttribute->GetArray<T>();
return defaultValue;
}
//-----------------------------------------------------------------------------
// Creates a dmx element
//-----------------------------------------------------------------------------
CDmxElement* CreateDmxElement( const char *pType );
//-----------------------------------------------------------------------------
// Helper class to lock elements for changes
//-----------------------------------------------------------------------------
class CDmxElementModifyScope
{
public:
CDmxElementModifyScope( CDmxElement *pElement ) : m_pElement( pElement )
{
m_pElement->LockForChanges( true );
}
~CDmxElementModifyScope()
{
Release();
}
void Release()
{
if ( m_pElement )
{
m_pElement->LockForChanges( false );
m_pElement = NULL;
}
}
private:
CDmxElement *m_pElement;
};
//-----------------------------------------------------------------------------
// Set methods
//-----------------------------------------------------------------------------
inline CDmxAttribute* CDmxElement::SetValue( const char *pAttributeName, const char *pString )
{
CDmxElementModifyScope modify( this );
CDmxAttribute *pAttribute = AddAttribute( pAttributeName );
pAttribute->SetValue( pString );
return pAttribute;
}
inline CDmxAttribute* CDmxElement::SetValue( const char *pAttributeName, void *pBuffer, int nLen )
{
CDmxElementModifyScope modify( this );
CDmxAttribute *pAttribute = AddAttribute( pAttributeName );
pAttribute->SetValue( pBuffer, nLen );
return pAttribute;
}
template< class T >
inline CDmxAttribute* CDmxElement::SetValue( const char *pAttributeName, const T& value )
{
CDmxElementModifyScope modify( this );
CDmxAttribute *pAttribute = AddAttribute( pAttributeName );
pAttribute->SetValue( value );
return pAttribute;
}
#endif // DMXELEMENT_H

View File

@ -0,0 +1,72 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef DMXLOADER_H
#define DMXLOADER_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CUtlBuffer;
class CDmxElement;
//-----------------------------------------------------------------------------
// Serialization/Unserialization
//-----------------------------------------------------------------------------
bool SerializeDMX( CUtlBuffer &buf, CDmxElement *pRoot, const char *pFileName = NULL );
bool SerializeDMX( const char *pFileName, const char *pPathID, bool bTextMode, CDmxElement *pRoot );
bool UnserializeDMX( CUtlBuffer &buf, CDmxElement **ppRoot, const char *pFileName = NULL );
bool UnserializeDMX( const char *pFileName, const char *pPathID, bool bTextMode, CDmxElement **ppRoot );
//-----------------------------------------------------------------------------
// DMX elements/attributes can only be accessed inside a dmx context
//-----------------------------------------------------------------------------
void BeginDMXContext( );
void EndDMXContext( bool bDecommitMemory );
void DecommitDMXMemory();
//-----------------------------------------------------------------------------
// Helper macro
//-----------------------------------------------------------------------------
class CDMXContextHelper
{
public:
CDMXContextHelper( bool bDecommitMemory ) { m_bDecommitMemory = bDecommitMemory; BeginDMXContext(); }
~CDMXContextHelper() { EndDMXContext( m_bDecommitMemory ); }
private:
bool m_bDecommitMemory;
};
#define DECLARE_DMX_CONTEXT( ) CDMXContextHelper __dmxContextHelper( true );
#define DECLARE_DMX_CONTEXT_NODECOMMIT( ) CDMXContextHelper __dmxContextHelper( false );
#define DECLARE_DMX_CONTEXT_DECOMMIT( _decommit ) CDMXContextHelper __dmxContextHelper( _decommit );
//-----------------------------------------------------------------------------
// Used for allocation. All will be freed when we leave the DMX context
//-----------------------------------------------------------------------------
void* DMXAlloc( size_t size );
//-----------------------------------------------------------------------------
// Helper macro
//-----------------------------------------------------------------------------
#define DECLARE_DMX_ALLOCATOR( ) \
public: \
inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_( "DMXAlloc" ); return DMXAlloc(size); } \
inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_( "DMXAlloc" ); return DMXAlloc(size); } \
inline void operator delete( void* p ) { } \
inline void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ) { } \
#endif // DMXLOADER_H

223
public/dt_common.h Normal file
View File

@ -0,0 +1,223 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef DATATABLE_COMMON_H
#define DATATABLE_COMMON_H
#ifdef _WIN32
#pragma once
#endif
#include "basetypes.h"
#include "tier0/dbg.h"
#include "tier1/strtools.h"
#include <stddef.h>
#ifdef LINUX
#undef offsetof
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif
// Max number of properties in a datatable and its children.
#define MAX_DATATABLES 1024 // must be a power of 2.
#define MAX_DATATABLE_PROPS 4096
#define MAX_ARRAY_ELEMENTS 2048 // a network array should have more that 1024 elements
#define HIGH_DEFAULT -121121.121121f
#define BITS_FULLRES -1 // Use the full resolution of the type being encoded.
#define BITS_WORLDCOORD -2 // Encode as a world coordinate.
#define DT_MAX_STRING_BITS 9
#define DT_MAX_STRING_BUFFERSIZE (1<<DT_MAX_STRING_BITS) // Maximum length of a string that can be sent.
#define STRINGBUFSIZE(className, varName) sizeof( ((className*)0)->varName )
// Gets the size of a variable in a class.
#define PROPSIZEOF(className, varName) sizeof(((className*)0)->varName)
// SendProp::m_Flags.
#define SPROP_UNSIGNED (1<<0) // Unsigned integer data.
#define SPROP_COORD (1<<1) // If this is set, the float/vector is treated like a world coordinate.
// Note that the bit count is ignored in this case.
#define SPROP_NOSCALE (1<<2) // For floating point, don't scale into range, just take value as is.
#define SPROP_ROUNDDOWN (1<<3) // For floating point, limit high value to range minus one bit unit
#define SPROP_ROUNDUP (1<<4) // For floating point, limit low value to range minus one bit unit
#define SPROP_NORMAL (1<<5) // If this is set, the vector is treated like a normal (only valid for vectors)
#define SPROP_EXCLUDE (1<<6) // This is an exclude prop (not excludED, but it points at another prop to be excluded).
#define SPROP_XYZE (1<<7) // Use XYZ/Exponent encoding for vectors.
#define SPROP_INSIDEARRAY (1<<8) // This tells us that the property is inside an array, so it shouldn't be put into the
// flattened property list. Its array will point at it when it needs to.
#define SPROP_PROXY_ALWAYS_YES (1<<9) // Set for datatable props using one of the default datatable proxies like
// SendProxy_DataTableToDataTable that always send the data to all clients.
#define SPROP_CHANGES_OFTEN (1<<10) // this is an often changed field, moved to head of sendtable so it gets a small index
#define SPROP_IS_A_VECTOR_ELEM (1<<11) // Set automatically if SPROP_VECTORELEM is used.
#define SPROP_COLLAPSIBLE (1<<12) // Set automatically if it's a datatable with an offset of 0 that doesn't change the pointer
// (ie: for all automatically-chained base classes).
// In this case, it can get rid of this SendPropDataTable altogether and spare the
// trouble of walking the hierarchy more than necessary.
#define SPROP_COORD_MP (1<<13) // Like SPROP_COORD, but special handling for multiplayer games
#define SPROP_COORD_MP_LOWPRECISION (1<<14) // Like SPROP_COORD, but special handling for multiplayer games where the fractional component only gets a 3 bits instead of 5
#define SPROP_COORD_MP_INTEGRAL (1<<15) // SPROP_COORD_MP, but coordinates are rounded to integral boundaries
#define SPROP_VARINT SPROP_NORMAL // reuse existing flag so we don't break demo. note you want to include SPROP_UNSIGNED if needed, its more efficient
#define SPROP_NUMFLAGBITS_NETWORKED 16
// This is server side only, it's used to mark properties whose SendProxy_* functions encode against gpGlobals->tickcount (the only ones that currently do this are
// m_flAnimTime and m_flSimulationTime. MODs shouldn't need to mess with this probably
#define SPROP_ENCODED_AGAINST_TICKCOUNT (1<<16)
// See SPROP_NUMFLAGBITS_NETWORKED for the ones which are networked
#define SPROP_NUMFLAGBITS 17
// Used by the SendProp and RecvProp functions to disable debug checks on type sizes.
#define SIZEOF_IGNORE -1
// Use this to extern send and receive datatables, and reference them.
#define EXTERN_SEND_TABLE(tableName) namespace tableName {extern SendTable g_SendTable;}
#define EXTERN_RECV_TABLE(tableName) namespace tableName {extern RecvTable g_RecvTable;}
#define REFERENCE_SEND_TABLE(tableName) tableName::g_SendTable
#define REFERENCE_RECV_TABLE(tableName) tableName::g_RecvTable
class SendProp;
// The day we do this, we break all mods until they recompile.
//#define SUPPORTS_INT64
typedef enum
{
DPT_Int=0,
DPT_Float,
DPT_Vector,
DPT_VectorXY, // Only encodes the XY of a vector, ignores Z
DPT_String,
DPT_Array, // An array of the base types (can't be of datatables).
DPT_DataTable,
#if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!!
DPT_Quaternion,
#endif
#ifdef SUPPORTS_INT64
DPT_Int64,
#endif
DPT_NUMSendPropTypes
} SendPropType;
class DVariant
{
public:
DVariant() {m_Type = DPT_Float;}
DVariant(float val) {m_Type = DPT_Float; m_Float = val;}
const char *ToString()
{
static char text[128];
switch ( m_Type )
{
case DPT_Int :
Q_snprintf( text, sizeof(text), "%i", m_Int );
break;
case DPT_Float :
Q_snprintf( text, sizeof(text), "%.3f", m_Float );
break;
case DPT_Vector :
Q_snprintf( text, sizeof(text), "(%.3f,%.3f,%.3f)",
m_Vector[0], m_Vector[1], m_Vector[2] );
break;
case DPT_VectorXY :
Q_snprintf( text, sizeof(text), "(%.3f,%.3f)",
m_Vector[0], m_Vector[1] );
break;
#if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!!
case DPT_Quaternion :
Q_snprintf( text, sizeof(text), "(%.3f,%.3f,%.3f %.3f)",
m_Vector[0], m_Vector[1], m_Vector[2], m_Vector[3] );
break;
#endif
case DPT_String :
if ( m_pString )
return m_pString;
else
return "NULL";
break;
case DPT_Array :
Q_snprintf( text, sizeof(text), "Array" );
break;
case DPT_DataTable :
Q_snprintf( text, sizeof(text), "DataTable" );
break;
#ifdef SUPPORTS_INT64
case DPT_Int64:
Q_snprintf( text, sizeof(text), "%I64d", m_Int64 );
break;
#endif
default :
Q_snprintf( text, sizeof(text), "DVariant type %i unknown", m_Type );
break;
}
return text;
}
union
{
float m_Float;
long m_Int;
const char *m_pString;
void *m_pData; // For DataTables.
#if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!!
float m_Vector[4];
#else
float m_Vector[3];
#endif
#ifdef SUPPORTS_INT64
int64 m_Int64;
#endif
};
SendPropType m_Type;
};
// This can be used to set the # of bits used to transmit a number between 0 and nMaxElements-1.
inline int NumBitsForCount( int nMaxElements )
{
int nBits = 0;
while ( nMaxElements > 0 )
{
++nBits;
nMaxElements >>= 1;
}
return nBits;
}
#endif // DATATABLE_COMMON_H

Some files were not shown because too many files have changed in this diff Show More