This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions

235
tier2/beamsegdraw.cpp Normal file
View File

@ -0,0 +1,235 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "tier2/beamsegdraw.h"
#include "materialsystem/imaterialvar.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
//
// CBeamSegDraw implementation.
//
//-----------------------------------------------------------------------------
void CBeamSegDraw::Start( IMatRenderContext *pRenderContext, int nSegs, IMaterial *pMaterial, CMeshBuilder *pMeshBuilder, int nMeshVertCount )
{
m_pRenderContext = pRenderContext;
Assert( nSegs >= 2 );
m_nSegsDrawn = 0;
m_nTotalSegs = nSegs;
if ( pMeshBuilder )
{
m_pMeshBuilder = pMeshBuilder;
m_nMeshVertCount = nMeshVertCount;
}
else
{
m_pMeshBuilder = NULL;
m_nMeshVertCount = 0;
IMesh *pMesh = m_pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial );
m_Mesh.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, (nSegs-1) * 2 );
}
}
inline void CBeamSegDraw::ComputeNormal( const Vector &vecCameraPos, const Vector &vStartPos, const Vector &vNextPos, Vector *pNormal )
{
// vTangentY = line vector for beam
Vector vTangentY;
VectorSubtract( vStartPos, vNextPos, vTangentY );
// vDirToBeam = vector from viewer origin to beam
Vector vDirToBeam;
VectorSubtract( vStartPos, vecCameraPos, vDirToBeam );
// Get a vector that is perpendicular to us and perpendicular to the beam.
// This is used to fatten the beam.
CrossProduct( vTangentY, vDirToBeam, *pNormal );
VectorNormalizeFast( *pNormal );
}
inline void CBeamSegDraw::SpecifySeg( const Vector &vecCameraPos, const Vector &vNormal )
{
// SUCKY: Need to do a fair amount more work to get the tangent owing to the averaged normal
Vector vDirToBeam, vTangentY;
VectorSubtract( m_Seg.m_vPos, vecCameraPos, vDirToBeam );
CrossProduct( vDirToBeam, vNormal, vTangentY );
VectorNormalizeFast( vTangentY );
// Build the endpoints.
Vector vPoint1, vPoint2;
VectorMA( m_Seg.m_vPos, m_Seg.m_flWidth*0.5f, vNormal, vPoint1 );
VectorMA( m_Seg.m_vPos, -m_Seg.m_flWidth*0.5f, vNormal, vPoint2 );
if ( m_pMeshBuilder )
{
// Specify the points.
m_pMeshBuilder->Position3fv( vPoint1.Base() );
m_pMeshBuilder->Color4f( VectorExpand( m_Seg.m_vColor ), m_Seg.m_flAlpha );
m_pMeshBuilder->TexCoord2f( 0, 0, m_Seg.m_flTexCoord );
m_pMeshBuilder->TexCoord2f( 1, 0, m_Seg.m_flTexCoord );
m_pMeshBuilder->TangentS3fv( vNormal.Base() );
m_pMeshBuilder->TangentT3fv( vTangentY.Base() );
m_pMeshBuilder->AdvanceVertex();
m_pMeshBuilder->Position3fv( vPoint2.Base() );
m_pMeshBuilder->Color4f( VectorExpand( m_Seg.m_vColor ), m_Seg.m_flAlpha );
m_pMeshBuilder->TexCoord2f( 0, 1, m_Seg.m_flTexCoord );
m_pMeshBuilder->TexCoord2f( 1, 1, m_Seg.m_flTexCoord );
m_pMeshBuilder->TangentS3fv( vNormal.Base() );
m_pMeshBuilder->TangentT3fv( vTangentY.Base() );
m_pMeshBuilder->AdvanceVertex();
if ( m_nSegsDrawn > 1 )
{
int nBase = ( ( m_nSegsDrawn - 2 ) * 2 ) + m_nMeshVertCount;
m_pMeshBuilder->FastIndex( nBase );
m_pMeshBuilder->FastIndex( nBase + 1 );
m_pMeshBuilder->FastIndex( nBase + 2 );
m_pMeshBuilder->FastIndex( nBase + 1 );
m_pMeshBuilder->FastIndex( nBase + 3 );
m_pMeshBuilder->FastIndex( nBase + 2 );
}
}
else
{
// Specify the points.
m_Mesh.Position3fv( vPoint1.Base() );
m_Mesh.Color4f( VectorExpand( m_Seg.m_vColor ), m_Seg.m_flAlpha );
m_Mesh.TexCoord2f( 0, 0, m_Seg.m_flTexCoord );
m_Mesh.TexCoord2f( 1, 0, m_Seg.m_flTexCoord );
m_Mesh.TangentS3fv( vNormal.Base() );
m_Mesh.TangentT3fv( vTangentY.Base() );
m_Mesh.AdvanceVertex();
m_Mesh.Position3fv( vPoint2.Base() );
m_Mesh.Color4f( VectorExpand( m_Seg.m_vColor ), m_Seg.m_flAlpha );
m_Mesh.TexCoord2f( 0, 1, m_Seg.m_flTexCoord );
m_Mesh.TexCoord2f( 1, 1, m_Seg.m_flTexCoord );
m_Mesh.TangentS3fv( vNormal.Base() );
m_Mesh.TangentT3fv( vTangentY.Base() );
m_Mesh.AdvanceVertex();
}
}
void CBeamSegDraw::NextSeg( BeamSeg_t *pSeg )
{
Vector vecCameraPos;
m_pRenderContext->GetWorldSpaceCameraPosition( &vecCameraPos );
if ( m_nSegsDrawn > 0 )
{
// Get a vector that is perpendicular to us and perpendicular to the beam.
// This is used to fatten the beam.
Vector vNormal, vAveNormal;
ComputeNormal( vecCameraPos, m_Seg.m_vPos, pSeg->m_vPos, &vNormal );
if ( m_nSegsDrawn > 1 )
{
// Average this with the previous normal
VectorAdd( vNormal, m_vNormalLast, vAveNormal );
vAveNormal *= 0.5f;
VectorNormalizeFast( vAveNormal );
}
else
{
vAveNormal = vNormal;
}
m_vNormalLast = vNormal;
SpecifySeg( vecCameraPos, vAveNormal );
}
m_Seg = *pSeg;
++m_nSegsDrawn;
if( m_nSegsDrawn == m_nTotalSegs )
{
SpecifySeg( vecCameraPos, m_vNormalLast );
}
}
void CBeamSegDraw::End()
{
if ( m_pMeshBuilder )
{
m_pMeshBuilder = NULL;
return;
}
m_Mesh.End( false, true );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBeamSegDrawArbitrary::SetNormal( const Vector &normal )
{
m_vNormalLast = normal;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBeamSegDrawArbitrary::NextSeg( BeamSeg_t *pSeg )
{
if ( m_nSegsDrawn > 0 )
{
Vector segDir = ( m_PrevSeg.m_vPos - pSeg->m_vPos );
VectorNormalize( segDir );
Vector normal = CrossProduct( segDir, m_vNormalLast );
SpecifySeg( normal );
}
m_PrevSeg = m_Seg;
m_Seg = *pSeg;
++m_nSegsDrawn;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : &vNextPos -
//-----------------------------------------------------------------------------
void CBeamSegDrawArbitrary::SpecifySeg( const Vector &vNormal )
{
// Build the endpoints.
Vector vPoint1, vPoint2;
Vector vDelta;
VectorMultiply( vNormal, m_Seg.m_flWidth*0.5f, vDelta );
VectorAdd( m_Seg.m_vPos, vDelta, vPoint1 );
VectorSubtract( m_Seg.m_vPos, vDelta, vPoint2 );
// Specify the points.
Assert( IsFinite(m_Seg.m_vColor.x) && IsFinite(m_Seg.m_vColor.y) && IsFinite(m_Seg.m_vColor.z) && IsFinite(m_Seg.m_flAlpha) );
Assert( (m_Seg.m_vColor.x >= 0.0) && (m_Seg.m_vColor.y >= 0.0) && (m_Seg.m_vColor.z >= 0.0) && (m_Seg.m_flAlpha >= 0.0) );
Assert( (m_Seg.m_vColor.x <= 1.0) && (m_Seg.m_vColor.y <= 1.0) && (m_Seg.m_vColor.z <= 1.0) && (m_Seg.m_flAlpha <= 1.0) );
unsigned char r = FastFToC( m_Seg.m_vColor.x );
unsigned char g = FastFToC( m_Seg.m_vColor.y );
unsigned char b = FastFToC( m_Seg.m_vColor.z );
unsigned char a = FastFToC( m_Seg.m_flAlpha );
m_Mesh.Position3fv( vPoint1.Base() );
m_Mesh.Color4ub( r, g, b, a );
m_Mesh.TexCoord2f( 0, 0, m_Seg.m_flTexCoord );
m_Mesh.TexCoord2f( 1, 0, m_Seg.m_flTexCoord );
m_Mesh.AdvanceVertex();
m_Mesh.Position3fv( vPoint2.Base() );
m_Mesh.Color4ub( r, g, b, a );
m_Mesh.TexCoord2f( 0, 1, m_Seg.m_flTexCoord );
m_Mesh.TexCoord2f( 1, 1, m_Seg.m_flTexCoord );
m_Mesh.AdvanceVertex();
}

99
tier2/camerautils.cpp Normal file
View File

@ -0,0 +1,99 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "tier2/camerautils.h"
#include "tier0/dbg.h"
#include "mathlib/vector.h"
#include "mathlib/vmatrix.h"
#include "tier2/tier2.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// accessors for generated matrices
//-----------------------------------------------------------------------------
void ComputeViewMatrix( matrix3x4_t *pWorldToCamera, const Camera_t &camera )
{
matrix3x4_t transform;
AngleMatrix( camera.m_angles, camera.m_origin, transform );
VMatrix matRotate( transform );
VMatrix matRotateZ;
MatrixBuildRotationAboutAxis( matRotateZ, Vector(0,0,1), -90 );
MatrixMultiply( matRotate, matRotateZ, matRotate );
VMatrix matRotateX;
MatrixBuildRotationAboutAxis( matRotateX, Vector(1,0,0), 90 );
MatrixMultiply( matRotate, matRotateX, matRotate );
transform = matRotate.As3x4();
MatrixInvert( transform, *pWorldToCamera );
}
void ComputeViewMatrix( VMatrix *pWorldToCamera, const Camera_t &camera )
{
matrix3x4_t transform, invTransform;
AngleMatrix( camera.m_angles, camera.m_origin, transform );
VMatrix matRotate( transform );
VMatrix matRotateZ;
MatrixBuildRotationAboutAxis( matRotateZ, Vector(0,0,1), -90 );
MatrixMultiply( matRotate, matRotateZ, matRotate );
VMatrix matRotateX;
MatrixBuildRotationAboutAxis( matRotateX, Vector(1,0,0), 90 );
MatrixMultiply( matRotate, matRotateX, matRotate );
transform = matRotate.As3x4();
MatrixInvert( transform, invTransform );
*pWorldToCamera = invTransform;
}
void ComputeProjectionMatrix( VMatrix *pCameraToProjection, const Camera_t &camera, int width, int height )
{
float flFOV = camera.m_flFOV;
float flZNear = camera.m_flZNear;
float flZFar = camera.m_flZFar;
float flApsectRatio = (float)width / (float)height;
// MatrixBuildPerspective( proj, flFOV, flFOV * flApsectRatio, flZNear, flZFar );
#if 1
float halfWidth = tan( flFOV * M_PI / 360.0 );
float halfHeight = halfWidth / flApsectRatio;
#else
float halfHeight = tan( flFOV * M_PI / 360.0 );
float halfWidth = flApsectRatio * halfHeight;
#endif
memset( pCameraToProjection, 0, sizeof( VMatrix ) );
pCameraToProjection->m[0][0] = 1.0f / halfWidth;
pCameraToProjection->m[1][1] = 1.0f / halfHeight;
pCameraToProjection->m[2][2] = flZFar / ( flZNear - flZFar );
pCameraToProjection->m[3][2] = -1.0f;
pCameraToProjection->m[2][3] = flZNear * flZFar / ( flZNear - flZFar );
}
//-----------------------------------------------------------------------------
// Computes the screen space position given a screen size
//-----------------------------------------------------------------------------
void ComputeScreenSpacePosition( Vector2D *pScreenPosition, const Vector &vecWorldPosition,
const Camera_t &camera, int width, int height )
{
VMatrix view, proj, viewproj;
ComputeViewMatrix( &view, camera );
ComputeProjectionMatrix( &proj, camera, width, height );
MatrixMultiply( proj, view, viewproj );
Vector vecScreenPos;
Vector3DMultiplyPositionProjective( viewproj, vecWorldPosition, vecScreenPos );
pScreenPosition->x = ( vecScreenPos.x + 1.0f ) * width / 2.0f;
pScreenPosition->y = ( -vecScreenPos.y + 1.0f ) * height / 2.0f;
}

View File

@ -0,0 +1,57 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A higher level link library for general use in the game and tools.
//
//===========================================================================//
#include <tier0/platform.h>
#include <tier2/tier2.h>
#include <filesystem_init.h>
static CSysModule *g_pFullFileSystemModule = NULL;
void* DefaultCreateInterfaceFn(const char *pName, int *pReturnCode)
{
if ( pReturnCode )
{
*pReturnCode = 0;
}
return NULL;
}
void InitDefaultFileSystem( void )
{
AssertMsg( !g_pFullFileSystem, "Already set up the file system" );
if ( !Sys_LoadInterface( "filesystem_stdio", FILESYSTEM_INTERFACE_VERSION,
&g_pFullFileSystemModule, (void**)&g_pFullFileSystem ) )
{
if ( !Sys_LoadInterface( "filesystem_steam", FILESYSTEM_INTERFACE_VERSION,
&g_pFullFileSystemModule, (void**)&g_pFullFileSystem ) )
{
exit(0);
}
}
if ( !g_pFullFileSystem->Connect( DefaultCreateInterfaceFn ) )
{
exit(0);
}
if ( g_pFullFileSystem->Init() != INIT_OK )
{
exit(0);
}
g_pFullFileSystem->RemoveAllSearchPaths();
g_pFullFileSystem->AddSearchPath( "", "LOCAL", PATH_ADD_TO_HEAD );
}
void ShutdownDefaultFileSystem(void)
{
AssertMsg( g_pFullFileSystem, "File system not set up" );
g_pFullFileSystem->Shutdown();
g_pFullFileSystem->Disconnect();
Sys_UnloadModule( g_pFullFileSystemModule );
}

62
tier2/dmconnect.cpp Normal file
View File

@ -0,0 +1,62 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A higher level link library for general use in the game and tools.
//
//===========================================================================//
#include <tier2/tier2.h>
#include "datamodel/idatamodel.h"
#include "dmserializers/idmserializers.h"
//-----------------------------------------------------------------------------
// Set up methods related to datamodel interfaces
//-----------------------------------------------------------------------------
bool ConnectDataModel( CreateInterfaceFn factory )
{
if ( !g_pDataModel->Connect( factory ) )
return false;
if ( !g_pDmElementFramework->Connect( factory ) )
return false;
if ( !g_pDmSerializers->Connect( factory ) )
return false;
return true;
}
InitReturnVal_t InitDataModel()
{
InitReturnVal_t nRetVal;
nRetVal = g_pDataModel->Init( );
if ( nRetVal != INIT_OK )
return nRetVal;
nRetVal = g_pDmElementFramework->Init();
if ( nRetVal != INIT_OK )
return nRetVal;
nRetVal = g_pDmSerializers->Init();
if ( nRetVal != INIT_OK )
return nRetVal;
return INIT_OK;
}
void ShutdownDataModel()
{
g_pDmSerializers->Shutdown();
g_pDmElementFramework->Shutdown();
g_pDataModel->Shutdown( );
}
void DisconnectDataModel()
{
g_pDmSerializers->Disconnect();
g_pDmElementFramework->Disconnect();
g_pDataModel->Disconnect();
}

304
tier2/fileutils.cpp Normal file
View File

@ -0,0 +1,304 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Helper methods + classes for file access
//
//===========================================================================//
#include "tier2/fileutils.h"
#include "tier2/tier2.h"
#include "tier1/strtools.h"
#include "filesystem.h"
#include "tier0/icommandline.h"
#include "tier1/utlbuffer.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Builds a directory which is a subdirectory of the current mod
//-----------------------------------------------------------------------------
void GetModSubdirectory( const char *pSubDir, char *pBuf, int nBufLen )
{
// Compute starting directory
Assert( g_pFullFileSystem->GetSearchPath( "MOD_WRITE", false, NULL, 0 ) < nBufLen );
if ( g_pFullFileSystem->GetSearchPath( "MOD_WRITE", false, pBuf, nBufLen ) == 0 )
{
// if we didn't find MOD_WRITE, back to the old MOD
Assert( g_pFullFileSystem->GetSearchPath( "MOD", false, NULL, 0 ) < nBufLen );
g_pFullFileSystem->GetSearchPath( "MOD", false, pBuf, nBufLen );
}
char *pSemi = strchr( pBuf, ';' );
if ( pSemi )
{
*pSemi = 0;
}
Q_StripTrailingSlash( pBuf );
if ( pSubDir )
{
int nLen = Q_strlen( pSubDir );
Q_strncat( pBuf, "\\", nBufLen, 1 );
Q_strncat( pBuf, pSubDir, nBufLen, nLen );
}
Q_FixSlashes( pBuf );
}
//-----------------------------------------------------------------------------
// Builds a directory which is a subdirectory of the current mod's *content*
//-----------------------------------------------------------------------------
void GetModContentSubdirectory( const char *pSubDir, char *pBuf, int nBufLen )
{
char pTemp[ MAX_PATH ];
GetModSubdirectory( pSubDir, pTemp, sizeof(pTemp) );
ComputeModContentFilename( pTemp, pBuf, nBufLen );
}
//-----------------------------------------------------------------------------
// Generates a filename under the 'game' subdirectory given a subdirectory of 'content'
//-----------------------------------------------------------------------------
void ComputeModFilename( const char *pContentFileName, char *pBuf, size_t nBufLen )
{
char pRelativePath[ MAX_PATH ];
if ( !g_pFullFileSystem->FullPathToRelativePathEx( pContentFileName, "CONTENTROOT", pRelativePath, sizeof(pRelativePath) ) )
{
Q_strncpy( pBuf, pContentFileName, (int)nBufLen );
return;
}
char pGameRoot[ MAX_PATH ];
g_pFullFileSystem->GetSearchPath( "GAMEROOT", false, pGameRoot, sizeof(pGameRoot) );
char *pSemi = strchr( pGameRoot, ';' );
if ( pSemi )
{
*pSemi = 0;
}
Q_ComposeFileName( pGameRoot, pRelativePath, pBuf, (int)nBufLen );
}
//-----------------------------------------------------------------------------
// Generates a filename under the 'content' subdirectory given a subdirectory of 'game'
//-----------------------------------------------------------------------------
void ComputeModContentFilename( const char *pGameFileName, char *pBuf, size_t nBufLen )
{
char pRelativePath[ MAX_PATH ];
if ( !g_pFullFileSystem->FullPathToRelativePathEx( pGameFileName, "GAMEROOT", pRelativePath, sizeof(pRelativePath) ) )
{
Q_strncpy( pBuf, pGameFileName, (int)nBufLen );
return;
}
char pContentRoot[ MAX_PATH ];
g_pFullFileSystem->GetSearchPath( "CONTENTROOT", false, pContentRoot, sizeof(pContentRoot) );
char *pSemi = strchr( pContentRoot, ';' );
if ( pSemi )
{
*pSemi = 0;
}
Q_ComposeFileName( pContentRoot, pRelativePath, pBuf, (int)nBufLen );
}
//-----------------------------------------------------------------------------
// Purpose: Generates an Xbox 360 filename from a PC filename
//-----------------------------------------------------------------------------
char *CreateX360Filename( const char *pSourceName, char *pTargetName, int targetLen )
{
Q_StripExtension( pSourceName, pTargetName, targetLen );
int idx = Q_strlen( pTargetName );
// restore extension
Q_snprintf( pTargetName, targetLen, "%s.360%s", pTargetName, &pSourceName[idx] );
return pTargetName;
}
//-----------------------------------------------------------------------------
// Purpose: Generates a PC filename from a possible 360 name.
// Strips the .360. from filename.360.extension.
// Filenames might have multiple '.', need to be careful and only consider the
// last true extension. Complex filenames do occur:
// d:\foo\.\foo.dat
// d:\zip0.360.zip\foo.360.dat
// Returns source if no change needs to occur, othwerwise generates and
// returns target.
//-----------------------------------------------------------------------------
char *RestoreFilename( const char *pSourceName, char *pTargetName, int targetLen )
{
// find extension
// scan backward for '.', but not past a seperator
int end = V_strlen( pSourceName ) - 1;
while ( end > 0 && pSourceName[end] != '.' && !( pSourceName[end] == '\\' || pSourceName[end] == '/' ) )
{
--end;
}
if ( end >= 4 && pSourceName[end] == '.' && !V_strncmp( pSourceName + end - 4 , ".360", 4 ) )
{
// cull the .360, leave the trailing extension
end -= 4;
int length = MIN( end + 1, targetLen );
V_strncpy( pTargetName, pSourceName, length );
V_strncat( pTargetName, pSourceName + end + 4, targetLen );
return pTargetName;
}
// source filename is as expected
return (char *)pSourceName;
}
//-----------------------------------------------------------------------------
// Generate an Xbox 360 file if it doesn't exist or is out of date. This function determines
// the source and target path and whether the file needs to be generated. The caller provides
// a callback function to do the actual creation of the 360 file. "pExtraData" is for the caller to
// pass the address of any data that the callback function may need to access. This function
// is ONLY to be called by caller's who expect to have 360 versions of their file.
//-----------------------------------------------------------------------------
int UpdateOrCreate( const char *pSourceName, char *pTargetName, int targetLen, const char *pPathID, CreateCallback_t pfnCreate, bool bForce, void *pExtraData )
{
if ( pTargetName )
{
// caller could supply source as PC or 360 name, we want the PC filename
char szFixedSourceName[MAX_PATH];
pSourceName = RestoreFilename( pSourceName, szFixedSourceName, sizeof( szFixedSourceName ) );
// caller wants us to provide 360 named version of source
CreateX360Filename( pSourceName, pTargetName, targetLen );
}
// no conversion are performed by the game at runtime anymore
// SMB access was removed by the XDK for Vista....
return UOC_NOT_CREATED;
}
//-----------------------------------------------------------------------------
// Returns the search path as a list of paths
//-----------------------------------------------------------------------------
void GetSearchPath( CUtlVector< CUtlString > &path, const char *pPathID )
{
int nMaxLen = g_pFullFileSystem->GetSearchPath( pPathID, false, NULL, 0 );
char *pBuf = (char*)stackalloc( nMaxLen );
g_pFullFileSystem->GetSearchPath( pPathID, false, pBuf, nMaxLen );
char *pSemi;
while ( NULL != ( pSemi = strchr( pBuf, ';' ) ) )
{
*pSemi = 0;
path.AddToTail( pBuf );
pBuf = pSemi + 1;
}
path.AddToTail( pBuf );
}
//-----------------------------------------------------------------------------
// Given file name in the current dir generate a full path to it.
//-----------------------------------------------------------------------------
bool GenerateFullPath( const char *pFileName, char const *pPathID, char *pBuf, int nBufLen )
{
if ( V_IsAbsolutePath( pFileName ) )
{
V_strncpy( pBuf, pFileName, nBufLen );
return true;
}
const char *pFullPath = g_pFullFileSystem->RelativePathToFullPath( pFileName, pPathID, pBuf, nBufLen );
if ( pFullPath && Q_IsAbsolutePath( pFullPath ) )
return true;
char pDir[ MAX_PATH ];
if ( !g_pFullFileSystem->GetCurrentDirectory( pDir, sizeof( pDir ) ) )
return false;
V_ComposeFileName( pDir, pFileName, pBuf, nBufLen );
V_RemoveDotSlashes( pBuf );
return true;
}
//-----------------------------------------------------------------------------
// Builds a list of all files under a directory with a particular extension
//-----------------------------------------------------------------------------
void AddFilesToList( CUtlVector< CUtlString > &list, const char *pDirectory, const char *pPathID, const char *pExtension )
{
char pSearchString[MAX_PATH];
Q_snprintf( pSearchString, MAX_PATH, "%s\\*", pDirectory );
bool bIsAbsolute = Q_IsAbsolutePath( pDirectory );
// get the list of files
FileFindHandle_t hFind;
const char *pFoundFile = g_pFullFileSystem->FindFirstEx( pSearchString, pPathID, &hFind );
// add all the items
CUtlVector< CUtlString > subDirs;
for ( ; pFoundFile; pFoundFile = g_pFullFileSystem->FindNext( hFind ) )
{
char pChildPath[MAX_PATH];
Q_snprintf( pChildPath, MAX_PATH, "%s\\%s", pDirectory, pFoundFile );
if ( g_pFullFileSystem->FindIsDirectory( hFind ) )
{
if ( Q_strnicmp( pFoundFile, ".", 2 ) && Q_strnicmp( pFoundFile, "..", 3 ) )
{
subDirs.AddToTail( pChildPath );
}
continue;
}
// Check the extension matches
const char *pExt = Q_GetFileExtension( pFoundFile );
if ( !pExt || Q_stricmp( pExt, pExtension ) != 0 )
continue;
char pFullPathBuf[MAX_PATH];
char *pFullPath = pFullPathBuf;
if ( !bIsAbsolute )
{
g_pFullFileSystem->RelativePathToFullPath( pChildPath, pPathID, pFullPathBuf, sizeof(pFullPathBuf) );
}
else
{
pFullPath = pChildPath;
}
V_strlower( pFullPath );
Q_FixSlashes( pFullPath );
list.AddToTail( pFullPath );
}
g_pFullFileSystem->FindClose( hFind );
int nCount = subDirs.Count();
for ( int i = 0; i < nCount; ++i )
{
AddFilesToList( list, subDirs[i], pPathID, pExtension );
}
}
void CBaseFile::ReadLines( CUtlStringList &lineList, int nMaxLineLength )
{
char *pLine = ( char * ) stackalloc( nMaxLineLength );
while( ReadLine( pLine, nMaxLineLength ) )
{
char *pEOL = strchr( pLine, '\n' ); // kill the \n
if ( pEOL )
*pEOL = 0;
lineList.CopyAndAddToTail( pLine );
}
}
void CBaseFile::ReadFile( CUtlBuffer &fileData )
{
int nFileSize = Size();
fileData.EnsureCapacity( Size() );
int nSize = Read( fileData.Base(), nFileSize );
fileData.SeekPut( CUtlBuffer::SEEK_HEAD, nSize );
}

143
tier2/keybindings.cpp Normal file
View File

@ -0,0 +1,143 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#include "tier2/keybindings.h"
#include "tier2/tier2.h"
#include "inputsystem/iinputsystem.h"
#include "tier1/utlbuffer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Set a key binding
//-----------------------------------------------------------------------------
void CKeyBindings::SetBinding( ButtonCode_t code, const char *pBinding )
{
if ( code == BUTTON_CODE_INVALID || code == KEY_NONE )
return;
// free old bindings
if ( !m_KeyInfo[code].IsEmpty() )
{
// Exactly the same, don't re-bind and fragment memory
if ( !Q_stricmp( m_KeyInfo[code], pBinding ) )
return;
}
// allocate memory for new binding
m_KeyInfo[code] = pBinding;
}
void CKeyBindings::SetBinding( const char *pButtonName, const char *pBinding )
{
ButtonCode_t code = g_pInputSystem->StringToButtonCode( pButtonName );
SetBinding( code, pBinding );
}
void CKeyBindings::Unbind( ButtonCode_t code )
{
if ( code != KEY_NONE && code != BUTTON_CODE_INVALID )
{
m_KeyInfo[code] = "";
}
}
void CKeyBindings::Unbind( const char *pButtonName )
{
ButtonCode_t code = g_pInputSystem->StringToButtonCode( pButtonName );
Unbind( code );
}
void CKeyBindings::UnbindAll()
{
for ( int i = 0; i < BUTTON_CODE_LAST; i++ )
{
m_KeyInfo[i] = "";
}
}
//-----------------------------------------------------------------------------
// Count number of lines of bindings we'll be writing
//-----------------------------------------------------------------------------
int CKeyBindings::GetBindingCount( ) const
{
int nCount = 0;
for ( int i = 0; i < BUTTON_CODE_LAST; i++ )
{
if ( !m_KeyInfo[i].IsEmpty() )
{
nCount++;
}
}
return nCount;
}
//-----------------------------------------------------------------------------
// Writes lines containing "bind key value"
//-----------------------------------------------------------------------------
void CKeyBindings::WriteBindings( CUtlBuffer &buf )
{
for ( int i = 0; i < BUTTON_CODE_LAST; i++ )
{
if ( !m_KeyInfo[i].IsEmpty() )
{
const char *pButtonCode = g_pInputSystem->ButtonCodeToString( (ButtonCode_t)i );
buf.Printf( "bind \"%s\" \"%s\"\n", pButtonCode, m_KeyInfo[i].Get() );
}
}
}
//-----------------------------------------------------------------------------
// Returns the keyname to which a binding string is bound. E.g., if
// TAB is bound to +use then searching for +use will return "TAB"
//-----------------------------------------------------------------------------
const char *CKeyBindings::ButtonNameForBinding( const char *pBinding )
{
const char *pBind = pBinding;
if ( pBinding[0] == '+' )
{
++pBind;
}
for ( int i = 0; i < BUTTON_CODE_LAST; i++ )
{
if ( m_KeyInfo[i].IsEmpty() )
continue;
if ( m_KeyInfo[i][0] == '+' )
{
if ( !Q_stricmp( &m_KeyInfo[i].Get()[1], pBind ) )
return g_pInputSystem->ButtonCodeToString( (ButtonCode_t)i );
}
else
{
if ( !Q_stricmp( m_KeyInfo[i], pBind ) )
return g_pInputSystem->ButtonCodeToString( (ButtonCode_t)i );
}
}
return NULL;
}
const char *CKeyBindings::GetBindingForButton( ButtonCode_t code )
{
if ( m_KeyInfo[code].IsEmpty() )
return NULL;
return m_KeyInfo[ code ];
}

462
tier2/keyvaluesmacros.cpp Normal file
View File

@ -0,0 +1,462 @@
//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
//
//==================================================================================================
#include "filesystem.h"
#include "tier1/KeyValues.h"
#include "tier2/keyvaluesmacros.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//--------------------------------------------------------------------------------------------------
// Returns true if the passed string matches the filename style glob, false otherwise
// * matches any characters, ? matches any single character, otherwise case insensitive matching
//--------------------------------------------------------------------------------------------------
bool GlobMatch( const char *pszGlob, const char *pszString )
{
while ( ( *pszString != '\0' ) && ( *pszGlob != '*' ) )
{
if ( ( V_strnicmp( pszGlob, pszString, 1 ) != 0 ) && ( *pszGlob != '?' ) )
{
return false;
}
++pszGlob;
++pszString;
}
const char *pszGlobTmp = nullptr;
const char *pszStringTmp = nullptr;
while ( *pszString )
{
if ( *pszGlob == '*' )
{
++pszGlob;
if ( *pszGlob == '\0' )
{
return true;
}
pszGlobTmp = pszGlob;
pszStringTmp = pszString + 1;
}
else if ( ( V_strnicmp( pszGlob, pszString, 1 ) == 0 ) || ( *pszGlob == '?' ) )
{
++pszGlob;
++pszString;
}
else
{
pszGlob = pszGlobTmp;
pszString = pszStringTmp++;
}
}
while ( *pszGlob == '*' )
{
++pszGlob;
}
return *pszGlob == '\0';
}
//--------------------------------------------------------------------------------------------------
// Inserts pkvToInsert after pkvAfter but setting pkvAfter's NextKey to pkvInsert
//--------------------------------------------------------------------------------------------------
static void InsertKeyValuesAfter( KeyValues *pkvAfter, KeyValues *pkvToInsert )
{
Assert( pkvAfter );
Assert( pkvToInsert );
pkvToInsert->SetNextKey( pkvAfter->GetNextKey() );
pkvAfter->SetNextKey( pkvToInsert );
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
static KeyValues *ReplaceSubKeyWithCopy( KeyValues *pkvParent, KeyValues *pkvToReplace, KeyValues *pkvReplaceWith )
{
Assert( pkvReplaceWith->GetFirstSubKey() == nullptr );
KeyValues *pkvCopy = pkvReplaceWith->MakeCopy();
Assert( pkvCopy->GetFirstSubKey() == nullptr );
Assert( pkvCopy->GetNextKey() == nullptr );
InsertKeyValuesAfter( pkvToReplace, pkvCopy );
pkvParent->RemoveSubKey( pkvToReplace );
pkvToReplace->deleteThis();
return pkvCopy;
}
//--------------------------------------------------------------------------------------------------
// Handles a KeyValues #insert macro. Replaces the #insert KeyValues with the specified file
// if it can be loaded. This is not called #include because base KeyValue's already has #include
// but it has two issues. The #include is relative to the keyvalues, these paths are resolved
// normally via IFileSystem and #include only works at the top level, #insert works no matter
// how deep the #insert macro is
//--------------------------------------------------------------------------------------------------
static KeyValues *HandleKeyValuesMacro_Insert( KeyValues *pkvInsert, KeyValues *pkvParent )
{
const char *pszName = pkvInsert->GetName();
if ( V_stricmp( "#insert", pszName ) != 0 )
return nullptr;
// Have an #insert key
if ( pkvInsert->GetFirstSubKey() )
{
// Invalid, has sub keys
Msg( "Error: #insert on key with subkeys, can only do #insert with simple key/value with string value\n" );
return nullptr;
}
if ( pkvInsert->GetDataType() != KeyValues::TYPE_STRING )
{
// Invalid, value isn't a string
Msg( "Error: #insert on key without a data type of string, can only do #insert with simple key/value with string value\n" );
return nullptr;
}
const char *pszInsert = pkvInsert->GetString();
if ( !pszInsert && *pszInsert == '\0' )
{
// Invalid, value is empty string
Msg( "Error: #insert on key with empty string value, can only do #insert with simple key/value with string value\n" );
return nullptr;
}
FileHandle_t f = g_pFullFileSystem->Open( pszInsert, "rb" );
if ( !f )
{
// Invalid, couldn't open #insert file
Msg( "Error: #insert couldn't open file: %s\n", pszInsert );
return nullptr;
}
uint nFileSize = g_pFullFileSystem->Size( f );
if ( nFileSize == 0 )
{
// Invalid, empty file
Msg( "Error: #insert empty file: %s\n", pszInsert );
return nullptr;
}
uint nBufSize = g_pFullFileSystem->GetOptimalReadSize( f, nFileSize + 2 /* null termination */ + 8 /* "\"x\"\n{\n}\n" */ );
char *pBuf = ( char* )g_pFullFileSystem->AllocOptimalReadBuffer( f, nBufSize );
pBuf[0] = '"';
pBuf[1] = 'i';
pBuf[2] = '"';
pBuf[3] = '\n';
pBuf[4] = '{';
pBuf[5] = '\n';
bool bRetOK = ( g_pFullFileSystem->ReadEx( pBuf + 6, nBufSize - 6, nFileSize, f ) != 0 );
g_pFullFileSystem->Close( f );
KeyValues *pkvNew = nullptr;
if ( bRetOK )
{
pBuf[nFileSize + 6 + 0] = '}';
pBuf[nFileSize + 6 + 1] = '\n';
pBuf[nFileSize + 6 + 2] = '\0';
pBuf[nFileSize + 6 + 3] = '\0'; // Double NULL termination
pkvNew = new KeyValues( pszInsert );
bRetOK = pkvNew->LoadFromBuffer( pszInsert, pBuf, g_pFullFileSystem );
}
else
{
Msg( "Error: #insert couldn't read file: %s\n", pszInsert );
}
g_pFullFileSystem->FreeOptimalReadBuffer( pBuf );
KeyValues *pkvReturn = nullptr;
CUtlVector< KeyValues * > newKeyList;
if ( bRetOK )
{
KeyValues *pkvInsertAfter = pkvInsert;
KeyValues *pkvNewSubKey = pkvNew->GetFirstSubKey();
pkvReturn = pkvNewSubKey;
while ( pkvNewSubKey )
{
KeyValues *pkvNextNewSubKey = pkvNewSubKey->GetNextKey();
pkvNew->RemoveSubKey( pkvNewSubKey );
bool bFound = false;
if ( pkvNewSubKey->GetFirstSubKey() == nullptr )
{
for ( KeyValues *pkvChild = pkvParent->GetFirstSubKey(); pkvChild; pkvChild = pkvChild->GetNextKey() )
{
if ( pkvChild == pkvInsert )
continue;
if ( pkvChild->GetNameSymbol() == pkvNewSubKey->GetNameSymbol() )
{
bFound = true;
break;
}
}
}
if ( !bFound )
{
InsertKeyValuesAfter( pkvInsertAfter, pkvNewSubKey );
pkvInsertAfter = pkvNewSubKey;
newKeyList.AddToTail( pkvNewSubKey );
}
pkvNewSubKey = pkvNextNewSubKey;
}
pkvParent->RemoveSubKey( pkvInsert );
pkvInsert->deleteThis();
}
if ( pkvNew )
{
pkvNew->deleteThis();
}
for ( int i = 0; i < newKeyList.Count(); ++i )
{
HandleKeyValuesMacros( pkvParent, newKeyList[i] );
}
return pkvReturn;
}
//-----------------------------------------------------------------------------
// Merge pkvSrc over pkvDst, adding any new keys from src to dst but overwriting
// existing keys in dst with keys with matching names from src
//-----------------------------------------------------------------------------
static void UpdateKeyValuesBlock( KeyValues *pkvDst, KeyValues *pkvUpdate )
{
Assert( pkvDst->GetFirstSubKey() );
Assert( pkvUpdate->GetFirstSubKey() );
for ( KeyValues *pkvUpdateSubKey = pkvUpdate->GetFirstSubKey(); pkvUpdateSubKey; pkvUpdateSubKey = pkvUpdateSubKey->GetNextKey() )
{
const int nSrcName = pkvUpdateSubKey->GetNameSymbol();
if ( pkvUpdateSubKey->GetFirstSubKey() )
{
Msg( "Error: #update has a key with subkeys, only simple key/values are allowed for #update, skipping: %s\n", pkvUpdateSubKey->GetName() );
continue;
}
KeyValues *pkvNew = nullptr;
// Check for an existing key with the same name
for ( KeyValues *pkvDstSubKey = pkvDst->GetFirstSubKey(); pkvDstSubKey; pkvDstSubKey = pkvDstSubKey->GetNextKey() )
{
if ( pkvDstSubKey == pkvUpdate )
continue;
const int nDstName = pkvDstSubKey->GetNameSymbol();
if ( nSrcName == nDstName )
{
pkvNew = ReplaceSubKeyWithCopy( pkvDst, pkvDstSubKey, pkvUpdateSubKey );
break;
}
}
if ( !pkvNew )
{
// Didn't update an existing key, add a key
pkvNew = pkvUpdateSubKey->MakeCopy();
pkvDst->AddSubKey( pkvNew ); // TODO: Perhaps add this right after the #update block?
}
Assert( pkvNew );
// Do inserts right away
if ( !V_strcmp( pkvNew->GetName(), "#insert" ) )
{
while ( pkvNew )
{
pkvNew = HandleKeyValuesMacros( pkvNew, pkvDst );
}
}
}
}
//--------------------------------------------------------------------------------------------------
// Handle's #update macros
//
// An #update must be a KeyValue block with a KeyValue block as a parent. It will look at sibling
// KeyValue blocks which match an optional "#glob", or all sibling KeyValue blocks if no "#glob" is
// specified and will merge all of the #update block's subkeys into each sibling block.
// overwriting KeyValues if they already exist and adding new KeyValues if they don't.
//
// Example:
//
// Before:
//
// "example"
// {
// "wear_level_1"
// {
// "one" "one_val"
// "two" "two_val"
// }
// "wear_level_2"
// {
// "one" "one_val"
// "two" "two_val"
// }
// "subblock"
// {
// "one" "one_val"
// "two" "two_val"
// }
// "#update"
// {
// "#glob" "wear_level_*"
// "one" "updated_one_val"
// "three" "three_val"
// }
// }
//
// After:
//
// "example"
// {
// "wear_level_1"
// {
// "one" "updated_one_val"
// "two" "two_val"
// "three" "three_val"
// }
// "wear_level_2"
// {
// "one" "updated_one_val"
// "two" "two_val"
// "three" "three_val"
// }
// "subblock"
// {
// "one" "one_val"
// "two" "two_val"
// }
// }
//
//--------------------------------------------------------------------------------------------------
static KeyValues *HandleKeyValuesMacro_Update( KeyValues *pkvUpdate, KeyValues *pkvParent, bool *pbDidUpdate )
{
const char *pszName = pkvUpdate->GetName();
if ( V_stricmp( "#update", pszName ) != 0 )
return nullptr;
// Have an #update key
if ( pkvUpdate->GetFirstSubKey() == nullptr )
{
// Invalid, has sub keys
Msg( "Error: #insert on key without subkeys, can only do #update with a key with subkeys\n" );
return nullptr;
}
if ( pkvUpdate->GetDataType() != KeyValues::TYPE_NONE )
{
// Invalid, value isn't a TYPE_NONE
Msg( "Error: #update on key without a data type of NONE, can only do #update with a key with subkeys\n" );
return nullptr;
}
const char *pszGlob = nullptr;
KeyValues *pkvGlob = pkvUpdate->FindKey( "#glob" );
if ( !pkvGlob )
{
pkvGlob = pkvUpdate->FindKey( "glob" );
}
if ( pkvGlob )
{
pszGlob = pkvGlob->GetString( nullptr, nullptr );
pkvUpdate->RemoveSubKey( pkvGlob );
}
for ( KeyValues *pkvParentSubKey = pkvParent->GetFirstSubKey(); pkvParentSubKey; pkvParentSubKey = pkvParentSubKey->GetNextKey() )
{
if ( pkvParentSubKey == pkvUpdate )
continue;
if ( pszGlob && !GlobMatch( pszGlob, pkvParentSubKey->GetName() ) )
continue;
UpdateKeyValuesBlock( pkvParentSubKey, pkvUpdate );
}
KeyValues *pkvReturn = pkvUpdate->GetNextKey();
pkvParent->RemoveSubKey( pkvUpdate );
pkvUpdate->deleteThis();
if ( pbDidUpdate )
{
*pbDidUpdate = true;
}
return pkvReturn;
}
//--------------------------------------------------------------------------------------------------
// Main external extry point
//--------------------------------------------------------------------------------------------------
KeyValues *HandleKeyValuesMacros( KeyValues *kv, KeyValues *pkvParent /* = nullptr */ )
{
KeyValues *pkvNextKey = HandleKeyValuesMacro_Insert( kv, pkvParent );
if ( pkvNextKey )
{
Assert( kv->GetFirstSubKey() == nullptr );
return pkvNextKey;
}
bool bDidLocalUpdate = false;
pkvNextKey = HandleKeyValuesMacro_Update( kv, pkvParent, &bDidLocalUpdate );
if ( bDidLocalUpdate )
{
Assert( kv->GetFirstSubKey() != nullptr );
return pkvNextKey;
}
KeyValues *pkvSub = kv->GetFirstSubKey();
while ( pkvSub )
{
pkvSub = HandleKeyValuesMacros( pkvSub, kv );
}
return kv->GetNextKey();
}

104
tier2/meshutils.cpp Normal file
View File

@ -0,0 +1,104 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A set of utilities to render standard shapes
//
//===========================================================================//
#include "tier2/meshutils.h"
//-----------------------------------------------------------------------------
// Helper methods to create various standard index buffer types
//-----------------------------------------------------------------------------
void GenerateSequentialIndexBuffer( unsigned short* pIndices, int nIndexCount, int nFirstVertex )
{
if ( !pIndices )
return;
// Format the sequential buffer
for ( int i = 0; i < nIndexCount; ++i )
{
pIndices[i] = (unsigned short)( i + nFirstVertex );
}
}
void GenerateQuadIndexBuffer( unsigned short* pIndices, int nIndexCount, int nFirstVertex )
{
if ( !pIndices )
return;
// Format the quad buffer
int i;
int numQuads = nIndexCount / 6;
int baseVertex = nFirstVertex;
for ( i = 0; i < numQuads; ++i)
{
// Triangle 1
pIndices[0] = (unsigned short)( baseVertex );
pIndices[1] = (unsigned short)( baseVertex + 1 );
pIndices[2] = (unsigned short)( baseVertex + 2 );
// Triangle 2
pIndices[3] = (unsigned short)( baseVertex );
pIndices[4] = (unsigned short)( baseVertex + 2 );
pIndices[5] = (unsigned short)( baseVertex + 3 );
baseVertex += 4;
pIndices += 6;
}
}
void GeneratePolygonIndexBuffer( unsigned short* pIndices, int nIndexCount, int nFirstVertex )
{
if ( !pIndices )
return;
int i;
int numPolygons = nIndexCount / 3;
for ( i = 0; i < numPolygons; ++i)
{
// Triangle 1
pIndices[0] = (unsigned short)( nFirstVertex );
pIndices[1] = (unsigned short)( nFirstVertex + i + 1 );
pIndices[2] = (unsigned short)( nFirstVertex + i + 2 );
pIndices += 3;
}
}
void GenerateLineStripIndexBuffer( unsigned short* pIndices, int nIndexCount, int nFirstVertex )
{
if ( !pIndices )
return;
int i;
int numLines = nIndexCount / 2;
for ( i = 0; i < numLines; ++i)
{
pIndices[0] = (unsigned short)( nFirstVertex + i );
pIndices[1] = (unsigned short)( nFirstVertex + i + 1 );
pIndices += 2;
}
}
void GenerateLineLoopIndexBuffer( unsigned short* pIndices, int nIndexCount, int nFirstVertex )
{
if ( !pIndices )
{
return;
}
int i;
int numLines = nIndexCount / 2;
pIndices[0] = (unsigned short)( nFirstVertex + numLines - 1 );
pIndices[1] = (unsigned short)( nFirstVertex );
pIndices += 2;
for ( i = 1; i < numLines; ++i)
{
pIndices[0] = (unsigned short)( nFirstVertex + i - 1 );
pIndices[1] = (unsigned short)( nFirstVertex + i );
pIndices += 2;
}
}

138
tier2/p4helpers.cpp Normal file
View File

@ -0,0 +1,138 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "p4helpers.h"
#include "tier2/tier2.h"
#include "p4lib/ip4.h"
#ifdef PLATFORM_WINDOWS_PC
#include <Windows.h>
#endif // PLATFORM_WINDOWS_PC
//////////////////////////////////////////////////////////////////////////
//
// CP4File implementation
//
//////////////////////////////////////////////////////////////////////////
CP4File::CP4File( char const *szFilename )
{
#ifdef PLATFORM_WINDOWS_PC
// On windows, get the pathname of the file on disk first before using that as a perforce path
// this avoids invalid Adds(). Have to go through GetShortPathName and then GetLongPathName from
// the short path name
TCHAR szShortPathName[ MAX_PATH ] = TEXT( "" );
const DWORD shortRetVal = GetShortPathName( szFilename, szShortPathName, ARRAYSIZE( szShortPathName ) );
if ( shortRetVal > 0 && shortRetVal <= ARRAYSIZE( szShortPathName ) )
{
TCHAR szLongPathName[ MAX_PATH ] = TEXT( "" );
const DWORD longRetVal = GetLongPathName( szShortPathName, szLongPathName, ARRAYSIZE( szLongPathName ) );
if ( longRetVal > 0 && longRetVal <= ARRAYSIZE( szLongPathName ) )
{
m_sFilename = szLongPathName;
return;
}
}
#endif // PLATFORM_WINDOWS_PC
m_sFilename = szFilename;
}
CP4File::~CP4File()
{
}
bool CP4File::Edit( void )
{
if ( !p4 )
return true;
return p4->OpenFileForEdit( m_sFilename.String() );
}
bool CP4File::Add( void )
{
if ( !p4 )
return true;
return p4->OpenFileForAdd( m_sFilename.String() );
}
bool CP4File::Revert( void )
{
if ( !p4 )
return true;
return p4->RevertFile( m_sFilename.String() );
}
// Is the file in perforce?
bool CP4File::IsFileInPerforce()
{
if ( !p4 )
return false;
return p4->IsFileInPerforce( m_sFilename.String() );
}
bool CP4File::SetFileType(const CUtlString& desiredFileType)
{
if ( !p4 )
return false;
return p4->SetFileType( m_sFilename.String(), desiredFileType.String() );
}
//////////////////////////////////////////////////////////////////////////
//
// CP4Factory implementation
//
//////////////////////////////////////////////////////////////////////////
CP4Factory::CP4Factory()
{
}
CP4Factory::~CP4Factory()
{
}
bool CP4Factory::SetDummyMode( bool bDummyMode )
{
bool bOld = m_bDummyMode;
m_bDummyMode = bDummyMode;
return bOld;
}
void CP4Factory::SetOpenFileChangeList( const char *szChangeListName )
{
if ( !m_bDummyMode && p4 )
p4->SetOpenFileChangeList( szChangeListName );
}
CP4File *CP4Factory::AccessFile( char const *szFilename ) const
{
if ( !m_bDummyMode )
return new CP4File( szFilename );
else
return new CP4File_Dummy( szFilename );
}
// Default p4 factory
static CP4Factory s_static_p4_factory;
CP4Factory *g_p4factory = &s_static_p4_factory; // NULL before the factory constructs

916
tier2/renderutils.cpp Normal file
View File

@ -0,0 +1,916 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A set of utilities to render standard shapes
//
//===========================================================================//
#include "tier2/renderutils.h"
#include "tier2/tier2.h"
#include "tier1/KeyValues.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/imesh.h"
#include "materialsystem/imaterial.h"
#include "tier0/vprof.h"
#include "tier0/basetypes.h"
#include "togl/rendermechanism.h"
#if !defined(M_PI)
#define M_PI 3.14159265358979323846
#endif
//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------
static bool s_bMaterialsInitialized = false;
static IMaterial *s_pWireframe;
static IMaterial *s_pWireframeIgnoreZ;
static IMaterial *s_pVertexColor;
static IMaterial *s_pVertexColorIgnoreZ;
//-----------------------------------------------------------------------------
// Initializes standard materials
//-----------------------------------------------------------------------------
void InitializeStandardMaterials()
{
if ( s_bMaterialsInitialized )
return;
s_bMaterialsInitialized = true;
KeyValues *pVMTKeyValues = new KeyValues( "wireframe" );
pVMTKeyValues->SetInt( "$vertexcolor", 1 );
s_pWireframe = g_pMaterialSystem->CreateMaterial( "__utilWireframe", pVMTKeyValues );
pVMTKeyValues = new KeyValues( "wireframe" );
pVMTKeyValues->SetInt( "$vertexcolor", 1 );
pVMTKeyValues->SetInt( "$vertexalpha", 1 );
pVMTKeyValues->SetInt( "$ignorez", 1 );
s_pWireframeIgnoreZ = g_pMaterialSystem->CreateMaterial( "__utilWireframeIgnoreZ", pVMTKeyValues );
pVMTKeyValues = new KeyValues( "unlitgeneric" );
pVMTKeyValues->SetInt( "$vertexcolor", 1 );
pVMTKeyValues->SetInt( "$vertexalpha", 1 );
s_pVertexColor = g_pMaterialSystem->CreateMaterial( "__utilVertexColor", pVMTKeyValues );
pVMTKeyValues = new KeyValues( "unlitgeneric" );
pVMTKeyValues->SetInt( "$vertexcolor", 1 );
pVMTKeyValues->SetInt( "$vertexalpha", 1 );
pVMTKeyValues->SetInt( "$ignorez", 1 );
s_pVertexColorIgnoreZ = g_pMaterialSystem->CreateMaterial( "__utilVertexColorIgnoreZ", pVMTKeyValues );
}
void ShutdownStandardMaterials()
{
if ( !s_bMaterialsInitialized )
return;
s_bMaterialsInitialized = false;
s_pWireframe->DecrementReferenceCount();
s_pWireframe = NULL;
s_pWireframeIgnoreZ->DecrementReferenceCount();
s_pWireframeIgnoreZ = NULL;
s_pVertexColor->DecrementReferenceCount();
s_pVertexColor = NULL;
s_pVertexColorIgnoreZ->DecrementReferenceCount();
s_pVertexColorIgnoreZ = NULL;
}
//-----------------------------------------------------------------------------
// Renders a wireframe sphere
//-----------------------------------------------------------------------------
void RenderWireframeSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer )
{
InitializeStandardMaterials();
// Make one more coordinate because (u,v) is discontinuous.
++nTheta;
int nVertices = nPhi * nTheta;
int nIndices = ( nTheta - 1 ) * 4 * ( nPhi - 1 );
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
CMeshBuilder meshBuilder;
IMesh* pMesh = pRenderContext->GetDynamicMesh();
meshBuilder.Begin( pMesh, MATERIAL_LINES, nVertices, nIndices );
unsigned char chRed = c.r();
unsigned char chGreen = c.g();
unsigned char chBlue = c.b();
unsigned char chAlpha = c.a();
int i, j;
for ( i = 0; i < nPhi; ++i )
{
for ( j = 0; j < nTheta; ++j )
{
float u = j / ( float )( nTheta - 1 );
float v = i / ( float )( nPhi - 1 );
float theta = 2.0f * M_PI * u;
float phi = M_PI * v;
meshBuilder.Position3f( vCenter.x + ( flRadius * sin(phi) * cos(theta) ),
vCenter.y + ( flRadius * sin(phi) * sin(theta) ),
vCenter.z + ( flRadius * cos(phi) ) );
meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
meshBuilder.AdvanceVertex();
}
}
for ( i = 0; i < nPhi - 1; ++i )
{
for ( j = 0; j < nTheta - 1; ++j )
{
int idx = nTheta * i + j;
meshBuilder.Index( idx );
meshBuilder.AdvanceIndex();
meshBuilder.Index( idx + nTheta );
meshBuilder.AdvanceIndex();
meshBuilder.Index( idx );
meshBuilder.AdvanceIndex();
meshBuilder.Index( idx + 1 );
meshBuilder.AdvanceIndex();
}
}
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Draws a sphere
//-----------------------------------------------------------------------------
void RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi, Color c, IMaterial *pMaterial )
{
InitializeStandardMaterials();
CMatRenderContextPtr pRenderContext( materials );
unsigned char chRed = c.r();
unsigned char chGreen = c.g();
unsigned char chBlue = c.b();
unsigned char chAlpha = c.a();
// Two extra degenerate triangles per row (except the last one)
int nTriangles = 2 * nTheta * ( nPhi - 1 );
int nIndices = 2 * ( nTheta + 1 ) * ( nPhi - 1 );
if ( nTriangles == 0 )
return;
pRenderContext->Bind( pMaterial );
IMesh *pMesh = pRenderContext->GetDynamicMesh( );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLE_STRIP, nTriangles, nIndices );
// Build the index buffer.
float flOONPhi = 1.0f / (nPhi-1);
float flOONTheta = 1.0f / (nTheta-1);
int i, j;
for ( i = 0; i < nPhi; ++i )
{
for ( j = 0; j < nTheta; ++j )
{
float u = j / ( float )( nTheta - 1 );
float v = i / ( float )( nPhi - 1 );
float theta = 2.0f * M_PI * u;
float phi = M_PI * v;
Vector vecPos;
vecPos.x = flRadius * sin(phi) * cos(theta);
vecPos.y = flRadius * sin(phi) * sin(theta);
vecPos.z = flRadius * cos(phi);
Vector vecNormal = vecPos;
VectorNormalize(vecNormal);
vecPos += vCenter;
meshBuilder.Position3f( vecPos.x, vecPos.y, vecPos.z );
meshBuilder.Normal3f( vecNormal.x, vecNormal.y, vecNormal.z );
meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
meshBuilder.TexCoord2f( 0, j * flOONTheta, i * flOONPhi );
meshBuilder.AdvanceVertex();
}
}
// Emit the triangle strips.
int idx = 0;
for ( i = 0; i < nPhi - 1; ++i )
{
for ( j = 0; j < nTheta; ++j )
{
idx = nTheta * i + j;
meshBuilder.Index( idx + nTheta );
meshBuilder.AdvanceIndex();
meshBuilder.Index( idx );
meshBuilder.AdvanceIndex();
}
// Emit a degenerate triangle to skip to the next row without a connecting triangle
if ( i < nPhi - 2 )
{
meshBuilder.Index( idx );
meshBuilder.AdvanceIndex();
meshBuilder.Index( idx + nTheta + 1 );
meshBuilder.AdvanceIndex();
}
}
meshBuilder.End();
pMesh->Draw();
}
void RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer )
{
IMaterial *pMaterial = bZBuffer ? s_pVertexColor : s_pVertexColorIgnoreZ;
Color cActual( c.r(), c.g(), c.b(), c.a() );
RenderSphere( vCenter, flRadius, nTheta, nPhi, cActual, pMaterial );
}
//-----------------------------------------------------------------------------
// Box vertices
//-----------------------------------------------------------------------------
static int s_pBoxFaceIndices[6][4] =
{
{ 0, 4, 6, 2 }, // -x
{ 5, 1, 3, 7 }, // +x
{ 0, 1, 5, 4 }, // -y
{ 2, 6, 7, 3 }, // +y
{ 0, 2, 3, 1 }, // -z
{ 4, 5, 7, 6 } // +z
};
static int s_pBoxFaceIndicesInsideOut[6][4] =
{
{ 0, 2, 6, 4 }, // -x
{ 5, 7, 3, 1 }, // +x
{ 0, 4, 5, 1 }, // -y
{ 2, 3, 7, 6 }, // +y
{ 0, 1, 3, 2 }, // -z
{ 4, 6, 7, 5 } // +z
};
static void GenerateBoxVertices( const Vector &vOrigin, const QAngle& angles, const Vector &vMins, const Vector &vMaxs, Vector pVerts[8] )
{
// Build a rotation matrix from orientation
matrix3x4_t fRotateMatrix;
AngleMatrix( angles, fRotateMatrix );
Vector vecPos;
for ( int i = 0; i < 8; ++i )
{
vecPos[0] = ( i & 0x1 ) ? vMaxs[0] : vMins[0];
vecPos[1] = ( i & 0x2 ) ? vMaxs[1] : vMins[1];
vecPos[2] = ( i & 0x4 ) ? vMaxs[2] : vMins[2];
VectorRotate( vecPos, fRotateMatrix, pVerts[i] );
pVerts[i] += vOrigin;
}
}
//-----------------------------------------------------------------------------
// Renders a wireframe box relative to an origin
//-----------------------------------------------------------------------------
void RenderWireframeBox( const Vector &vOrigin, const QAngle& angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer )
{
InitializeStandardMaterials();
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
Vector p[8];
GenerateBoxVertices( vOrigin, angles, vMins, vMaxs, p );
unsigned char chRed = c.r();
unsigned char chGreen = c.g();
unsigned char chBlue = c.b();
unsigned char chAlpha = c.a();
IMesh *pMesh = pRenderContext->GetDynamicMesh( );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_LINES, 24 );
// Draw the box
for ( int i = 0; i < 6; i++ )
{
int *pFaceIndex = s_pBoxFaceIndices[i];
for ( int j = 0; j < 4; ++j )
{
meshBuilder.Position3fv( p[pFaceIndex[j]].Base() );
meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( p[pFaceIndex[ (j == 3) ? 0 : j+1 ] ].Base() );
meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
meshBuilder.AdvanceVertex();
}
}
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Renders a solid box
//-----------------------------------------------------------------------------
void RenderBox( const Vector& vOrigin, const QAngle& angles, const Vector& vMins, const Vector& vMaxs, Color c, IMaterial *pMaterial, bool bInsideOut )
{
InitializeStandardMaterials();
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->Bind( pMaterial );
Vector p[8];
GenerateBoxVertices( vOrigin, angles, vMins, vMaxs, p );
unsigned char chRed = c.r();
unsigned char chGreen = c.g();
unsigned char chBlue = c.b();
unsigned char chAlpha = c.a();
IMesh *pMesh = pRenderContext->GetDynamicMesh( );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, 12 );
// Draw the box
Vector vecNormal;
for ( int i = 0; i < 6; i++ )
{
vecNormal.Init();
vecNormal[ i/2 ] = ( i & 0x1 ) ? 1.0f : -1.0f;
int *ppFaceIndices = bInsideOut ? s_pBoxFaceIndicesInsideOut[i] : s_pBoxFaceIndices[i];
for ( int j = 1; j < 3; ++j )
{
int i0 = ppFaceIndices[0];
int i1 = ppFaceIndices[j];
int i2 = ppFaceIndices[j+1];
meshBuilder.Position3fv( p[i0].Base() );
meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
meshBuilder.Normal3fv( vecNormal.Base() );
meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( p[i2].Base() );
meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
meshBuilder.Normal3fv( vecNormal.Base() );
meshBuilder.TexCoord2f( 0, 1.0f, ( j == 1 ) ? 1.0f : 0.0f );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( p[i1].Base() );
meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
meshBuilder.Normal3fv( vecNormal.Base() );
meshBuilder.TexCoord2f( 0, ( j == 1 ) ? 0.0f : 1.0f, 1.0f );
meshBuilder.AdvanceVertex();
}
}
meshBuilder.End();
pMesh->Draw();
}
void RenderBox( const Vector& vOrigin, const QAngle& angles, const Vector& vMins, const Vector& vMaxs, Color c, bool bZBuffer, bool bInsideOut )
{
IMaterial *pMaterial = bZBuffer ? s_pVertexColor : s_pVertexColorIgnoreZ;
Color cActual( c.r(), c.g(), c.b(), c.a() );
RenderBox( vOrigin, angles, vMins, vMaxs, cActual, pMaterial, bInsideOut );
}
//-----------------------------------------------------------------------------
// Renders axes, red->x, green->y, blue->z
//-----------------------------------------------------------------------------
void RenderAxes( const Vector &vOrigin, float flScale, bool bZBuffer )
{
InitializeStandardMaterials();
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
IMesh *pMesh = pRenderContext->GetDynamicMesh( );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_LINES, 3 );
meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
meshBuilder.Color4ub( 255, 0, 0, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( vOrigin.x + flScale, vOrigin.y, vOrigin.z );
meshBuilder.Color4ub( 255, 0, 0, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
meshBuilder.Color4ub( 0, 255, 0, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( vOrigin.x, vOrigin.y + flScale, vOrigin.z );
meshBuilder.Color4ub( 0, 255, 0, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
meshBuilder.Color4ub( 0, 0, 255, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z + flScale );
meshBuilder.Color4ub( 0, 0, 255, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
}
void RenderAxes( const matrix3x4_t &transform, float flScale, bool bZBuffer )
{
InitializeStandardMaterials();
Vector xAxis, yAxis, zAxis, vOrigin, temp;
MatrixGetColumn( transform, 0, xAxis );
MatrixGetColumn( transform, 1, yAxis );
MatrixGetColumn( transform, 2, zAxis );
MatrixGetColumn( transform, 3, vOrigin );
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
IMesh *pMesh = pRenderContext->GetDynamicMesh( );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_LINES, 3 );
meshBuilder.Position3fv( vOrigin.Base() );
meshBuilder.Color4ub( 255, 0, 0, 255 );
meshBuilder.AdvanceVertex();
VectorMA( vOrigin, flScale, xAxis, temp );
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( 255, 0, 0, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
meshBuilder.Color4ub( 0, 255, 0, 255 );
meshBuilder.AdvanceVertex();
VectorMA( vOrigin, flScale, yAxis, temp );
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( 0, 255, 0, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( vOrigin.x, vOrigin.y, vOrigin.z );
meshBuilder.Color4ub( 0, 0, 255, 255 );
meshBuilder.AdvanceVertex();
VectorMA( vOrigin, flScale, zAxis, temp );
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( 0, 0, 255, 255 );
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Render a line
//-----------------------------------------------------------------------------
void RenderLine( const Vector& v1, const Vector& v2, Color c, bool bZBuffer )
{
InitializeStandardMaterials();
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
unsigned char chRed = c.r();
unsigned char chGreen = c.g();
unsigned char chBlue = c.b();
unsigned char chAlpha = c.a();
IMesh *pMesh = pRenderContext->GetDynamicMesh( );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_LINES, 1 );
meshBuilder.Position3fv( v1.Base() );
meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( v2.Base() );
meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Draws a triangle
//-----------------------------------------------------------------------------
void RenderTriangle( const Vector& p1, const Vector& p2, const Vector& p3, Color c, IMaterial *pMaterial )
{
InitializeStandardMaterials();
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->Bind( pMaterial );
unsigned char chRed = c.r();
unsigned char chGreen = c.g();
unsigned char chBlue = c.b();
unsigned char chAlpha = c.a();
Vector vecNormal;
Vector vecDelta1, vecDelta2;
VectorSubtract( p2, p1, vecDelta1 );
VectorSubtract( p3, p1, vecDelta2 );
CrossProduct( vecDelta1, vecDelta2, vecNormal );
VectorNormalize( vecNormal );
IMesh *pMesh = pRenderContext->GetDynamicMesh( );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, 1 );
meshBuilder.Position3fv( p1.Base() );
meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
meshBuilder.Normal3fv( vecNormal.Base() );
meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( p2.Base() );
meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
meshBuilder.Normal3fv( vecNormal.Base() );
meshBuilder.TexCoord2f( 0, 0.0f, 1.0f );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( p3.Base() );
meshBuilder.Color4ub( chRed, chGreen, chBlue, chAlpha );
meshBuilder.Normal3fv( vecNormal.Base() );
meshBuilder.TexCoord2f( 0, 1.0f, 0.0f );
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
}
void RenderTriangle( const Vector& p1, const Vector& p2, const Vector& p3, Color c, bool bZBuffer )
{
IMaterial *pMaterial = bZBuffer ? s_pVertexColor : s_pVertexColorIgnoreZ;
Color cActual( c.r(), c.g(), c.b(), c.a() );
RenderTriangle( p1, p2, p3, cActual, pMaterial );
}
//-----------------------------------------------------------------------------
// Renders an extruded box
//-----------------------------------------------------------------------------
static void DrawAxes( const Vector& origin, Vector* pts, int idx, Color c, CMeshBuilder& meshBuilder )
{
Vector start, temp;
VectorAdd( pts[idx], origin, start );
meshBuilder.Position3fv( start.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
int endidx = (idx & 0x1) ? idx - 1 : idx + 1;
VectorAdd( pts[endidx], origin, temp );
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( start.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
endidx = (idx & 0x2) ? idx - 2 : idx + 2;
VectorAdd( pts[endidx], origin, temp );
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( start.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
endidx = (idx & 0x4) ? idx - 4 : idx + 4;
VectorAdd( pts[endidx], origin, temp );
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
}
static void DrawExtrusionFace( const Vector& start, const Vector& end,
Vector* pts, int idx1, int idx2, Color c, CMeshBuilder& meshBuilder )
{
Vector temp;
VectorAdd( pts[idx1], start, temp );
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
VectorAdd( pts[idx2], start, temp );
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
VectorAdd( pts[idx2], end, temp );
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
VectorAdd( pts[idx1], end, temp );
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
VectorAdd( pts[idx1], start, temp );
meshBuilder.Position3fv( temp.Base() );
meshBuilder.Color4ub( c.r(), c.g(), c.b(), c.a() );
meshBuilder.AdvanceVertex();
}
void RenderWireframeSweptBox( const Vector &vStart, const Vector &vEnd, const QAngle &angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer )
{
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
pRenderContext->Bind( bZBuffer ? s_pWireframe : s_pWireframeIgnoreZ );
Color cActual( c.r(), c.g(), c.b(), c.a() );
// Build a rotation matrix from angles
matrix3x4_t fRotateMatrix;
AngleMatrix( angles, fRotateMatrix );
IMesh *pMesh = pRenderContext->GetDynamicMesh( );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_LINES, 30 );
Vector vDelta;
VectorSubtract( vEnd, vStart, vDelta );
// Compute the box points, rotated but without the origin added
Vector temp;
Vector pts[8];
float dot[8];
int minidx = 0;
for ( int i = 0; i < 8; ++i )
{
temp.x = (i & 0x1) ? vMaxs[0] : vMins[0];
temp.y = (i & 0x2) ? vMaxs[1] : vMins[1];
temp.z = (i & 0x4) ? vMaxs[2] : vMins[2];
// Rotate the corner point
VectorRotate( temp, fRotateMatrix, pts[i] );
// Find the dot product with dir
dot[i] = DotProduct( pts[i], vDelta );
if ( dot[i] < dot[minidx] )
{
minidx = i;
}
}
// Choose opposite corner
int maxidx = minidx ^ 0x7;
// Draw the start + end axes...
DrawAxes( vStart, pts, minidx, cActual, meshBuilder );
DrawAxes( vEnd, pts, maxidx, cActual, meshBuilder );
// Draw the extrusion faces
for (int j = 0; j < 3; ++j )
{
int dirflag1 = ( 1 << ((j+1)%3) );
int dirflag2 = ( 1 << ((j+2)%3) );
int idx1, idx2, idx3;
idx1 = (minidx & dirflag1) ? minidx - dirflag1 : minidx + dirflag1;
idx2 = (minidx & dirflag2) ? minidx - dirflag2 : minidx + dirflag2;
idx3 = (minidx & dirflag2) ? idx1 - dirflag2 : idx1 + dirflag2;
DrawExtrusionFace( vStart, vEnd, pts, idx1, idx3, cActual, meshBuilder );
DrawExtrusionFace( vStart, vEnd, pts, idx2, idx3, cActual, meshBuilder );
}
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Draws a axis-aligned quad
//-----------------------------------------------------------------------------
void RenderQuad( IMaterial *pMaterial, float x, float y, float w, float h,
float z, float s0, float t0, float s1, float t1, const Color& clr )
{
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a());
meshBuilder.TexCoord2f( 0, s0, t0 );
meshBuilder.Position3f( x, y, z );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a());
meshBuilder.TexCoord2f( 0, s1, t0 );
meshBuilder.Position3f( x + w, y, z );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a());
meshBuilder.TexCoord2f( 0, s1, t1 );
meshBuilder.Position3f( x + w, y + h, z );
meshBuilder.AdvanceVertex();
meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a());
meshBuilder.TexCoord2f( 0, s0, t1 );
meshBuilder.Position3f( x, y + h, z );
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Renders a screen space quad
//-----------------------------------------------------------------------------
void DrawScreenSpaceRectangle( IMaterial *pMaterial,
int nDestX, int nDestY, int nWidth, int nHeight, // Rect to draw into in screen space
float flSrcTextureX0, float flSrcTextureY0, // which texel you want to appear at destx/y
float flSrcTextureX1, float flSrcTextureY1, // which texel you want to appear at destx+width-1, desty+height-1
int nSrcTextureWidth, int nSrcTextureHeight, // needed for fixup
void *pClientRenderable, // Used to pass to the bind proxies
int nXDice, int nYDice, // Amount to tessellate the mesh
float fDepth ) // what Z value to put in the verts (def 0.0)
{
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
if ( ( nWidth <= 0 ) || ( nHeight <= 0 ) )
return;
tmZone( TELEMETRY_LEVEL1, TMZF_NONE, "%s", __FUNCTION__ );
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
pRenderContext->Bind( pMaterial, pClientRenderable );
int xSegments = max( nXDice, 1);
int ySegments = max( nYDice, 1);
CMeshBuilder meshBuilder;
IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
meshBuilder.Begin( pMesh, MATERIAL_QUADS, xSegments * ySegments );
int nScreenWidth, nScreenHeight;
pRenderContext->GetRenderTargetDimensions( nScreenWidth, nScreenHeight );
float flOffset = 0.5f;
float flLeftX = nDestX - flOffset;
float flRightX = nDestX + nWidth - flOffset;
float flTopY = nDestY - flOffset;
float flBottomY = nDestY + nHeight - flOffset;
float flSubrectWidth = flSrcTextureX1 - flSrcTextureX0;
float flSubrectHeight = flSrcTextureY1 - flSrcTextureY0;
float flTexelsPerPixelX = ( nWidth > 1 ) ? flSubrectWidth / ( nWidth - 1 ) : 0.0f;
float flTexelsPerPixelY = ( nHeight > 1 ) ? flSubrectHeight / ( nHeight - 1 ) : 0.0f;
float flLeftU = flSrcTextureX0 + 0.5f - ( 0.5f * flTexelsPerPixelX );
float flRightU = flSrcTextureX1 + 0.5f + ( 0.5f * flTexelsPerPixelX );
float flTopV = flSrcTextureY0 + 0.5f - ( 0.5f * flTexelsPerPixelY );
float flBottomV = flSrcTextureY1 + 0.5f + ( 0.5f * flTexelsPerPixelY );
float flOOTexWidth = 1.0f / nSrcTextureWidth;
float flOOTexHeight = 1.0f / nSrcTextureHeight;
flLeftU *= flOOTexWidth;
flRightU *= flOOTexWidth;
flTopV *= flOOTexHeight;
flBottomV *= flOOTexHeight;
// Get the current viewport size
int vx, vy, vw, vh;
pRenderContext->GetViewport( vx, vy, vw, vh );
// map from screen pixel coords to -1..1
flRightX = FLerp( -1, 1, 0, vw, flRightX );
flLeftX = FLerp( -1, 1, 0, vw, flLeftX );
flTopY = FLerp( 1, -1, 0, vh ,flTopY );
flBottomY = FLerp( 1, -1, 0, vh, flBottomY );
// Dice the quad up...
if ( ( xSegments > 1 ) || ( ySegments > 1 ) )
{
// Screen height and width of a subrect
float flWidth = (flRightX - flLeftX) / (float) xSegments;
float flHeight = (flTopY - flBottomY) / (float) ySegments;
// UV height and width of a subrect
float flUWidth = (flRightU - flLeftU) / (float) xSegments;
float flVHeight = (flBottomV - flTopV) / (float) ySegments;
for ( int x=0; x < xSegments; x++ )
{
for ( int y=0; y < ySegments; y++ )
{
// Top left
meshBuilder.Position3f( flLeftX + (float) x * flWidth, flTopY - (float) y * flHeight, fDepth );
meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
meshBuilder.TexCoord2f( 0, flLeftU + (float) x * flUWidth, flTopV + (float) y * flVHeight);
meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
meshBuilder.AdvanceVertex();
// Top right (x+1)
meshBuilder.Position3f( flLeftX + (float) (x+1) * flWidth, flTopY - (float) y * flHeight, fDepth );
meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
meshBuilder.TexCoord2f( 0, flLeftU + (float) (x+1) * flUWidth, flTopV + (float) y * flVHeight);
meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
meshBuilder.AdvanceVertex();
// Bottom right (x+1), (y+1)
meshBuilder.Position3f( flLeftX + (float) (x+1) * flWidth, flTopY - (float) (y+1) * flHeight, fDepth );
meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
meshBuilder.TexCoord2f( 0, flLeftU + (float) (x+1) * flUWidth, flTopV + (float)(y+1) * flVHeight);
meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
meshBuilder.AdvanceVertex();
// Bottom left (y+1)
meshBuilder.Position3f( flLeftX + (float) x * flWidth, flTopY - (float) (y+1) * flHeight, fDepth );
meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
meshBuilder.TexCoord2f( 0, flLeftU + (float) x * flUWidth, flTopV + (float)(y+1) * flVHeight);
meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
meshBuilder.AdvanceVertex();
}
}
}
else // just one quad
{
for ( int corner=0; corner<4; corner++ )
{
bool bLeft = (corner==0) || (corner==3);
meshBuilder.Position3f( (bLeft) ? flLeftX : flRightX, (corner & 2) ? flBottomY : flTopY, fDepth );
meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
meshBuilder.TexCoord2f( 0, (bLeft) ? flLeftU : flRightU, (corner & 2) ? flBottomV : flTopV );
meshBuilder.TangentS3f( 0.0f, 1.0f, 0.0f );
meshBuilder.TangentT3f( 1.0f, 0.0f, 0.0f );
meshBuilder.AdvanceVertex();
}
}
meshBuilder.End();
pMesh->Draw();
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PopMatrix();
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->PopMatrix();
}

506
tier2/riff.cpp Normal file
View File

@ -0,0 +1,506 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// Avoid these warnings:
#pragma warning(disable : 4512) // warning C4512: 'InFileRIFF' : assignment operator could not be generated
#pragma warning(disable : 4514) // warning C4514: 'RIFFName' : unreferenced inline function has been removed
#include "riff.h"
#include <stdio.h>
#include <string.h>
#include "tier0/dbg.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if 0
//-----------------------------------------------------------------------------
// Purpose: Test code that implements the interface on stdio
//-----------------------------------------------------------------------------
class StdIOReadBinary : public IFileReadBinary
{
public:
int open( const char *pFileName )
{
return (int)fopen( pFileName, "rb" );
}
int read( void *pOutput, int size, int file )
{
FILE *fp = (FILE *)file;
return fread( pOutput, size, 1, fp );
}
void seek( int file, int pos )
{
fseek( (FILE *)file, pos, SEEK_SET );
}
unsigned int tell( int file )
{
return ftell( (FILE *)file );
}
unsigned int size( int file )
{
FILE *fp = (FILE *)file;
if ( !fp )
return 0;
unsigned int pos = ftell( fp );
fseek( fp, 0, SEEK_END );
unsigned int size = ftell( fp );
fseek( fp, pos, SEEK_SET );
return size;
}
void close( int file )
{
FILE *fp = (FILE *)file;
fclose( fp );
}
};
#endif
#define RIFF_ID MAKEID('R','I','F','F')
//-----------------------------------------------------------------------------
// Purpose: Opens a RIFF file using the given I/O mechanism
// Input : *pFileName
// &io - I/O interface
//-----------------------------------------------------------------------------
InFileRIFF::InFileRIFF( const char *pFileName, IFileReadBinary &io ) : m_io(io)
{
m_file = m_io.open( pFileName );
int riff = 0;
if ( !m_file )
{
m_riffSize = 0;
m_riffName = 0;
return;
}
riff = ReadInt();
if ( riff != RIFF_ID )
{
printf( "Not a RIFF File [%s]\n", pFileName );
m_riffSize = 0;
}
else
{
// we store size as size of all chunks
// subtract off the RIFF form type (e.g. 'WAVE', 4 bytes)
m_riffSize = ReadInt() - 4;
m_riffName = ReadInt();
// HACKHACK: LWV files don't obey the RIFF format!!!
// Do this or miss the linguistic chunks at the end. Lame!
// subtract off 12 bytes for (RIFF, size, WAVE)
m_riffSize = m_io.size( m_file ) - 12;
}
}
//-----------------------------------------------------------------------------
// Purpose: Close the file
//-----------------------------------------------------------------------------
InFileRIFF::~InFileRIFF( void )
{
m_io.close( m_file );
}
//-----------------------------------------------------------------------------
// Purpose: read a 4-byte int out of the stream
// Output : int = read value, default is zero
//-----------------------------------------------------------------------------
int InFileRIFF::ReadInt( void )
{
int tmp = 0;
m_io.read( &tmp, sizeof(int), m_file );
tmp = LittleLong( tmp );
return tmp;
}
//-----------------------------------------------------------------------------
// Purpose: Read a block of binary data
// Input : *pOutput - pointer to destination memory
// dataSize - size of block to read
// Output : int - number of bytes read
//-----------------------------------------------------------------------------
int InFileRIFF::ReadData( void *pOutput, int dataSize )
{
int count = m_io.read( pOutput, dataSize, m_file );
return count;
}
//-----------------------------------------------------------------------------
// Purpose: Gets the file position
// Output : int (bytes from start of file)
//-----------------------------------------------------------------------------
int InFileRIFF::PositionGet( void )
{
return m_io.tell( m_file );
}
//-----------------------------------------------------------------------------
// Purpose: Seek to file position
// Input : position - bytes from start of file
//-----------------------------------------------------------------------------
void InFileRIFF::PositionSet( int position )
{
m_io.seek( m_file, position );
}
//-----------------------------------------------------------------------------
// Purpose: Used to write a RIFF format file
//-----------------------------------------------------------------------------
OutFileRIFF::OutFileRIFF( const char *pFileName, IFileWriteBinary &io ) : m_io( io )
{
m_file = m_io.create( pFileName );
if ( !m_file )
return;
int riff = RIFF_ID;
m_io.write( &riff, 4, m_file );
m_riffSize = 0;
m_nNamePos = m_io.tell( m_file );
// Save room for the size and name now
WriteInt( 0 );
// Write out the name
WriteInt( RIFF_WAVE );
m_bUseIncorrectLISETLength = false;
m_nLISETSize = 0;
}
OutFileRIFF::~OutFileRIFF( void )
{
if ( !IsValid() )
return;
unsigned int size = m_io.tell( m_file ) -8;
m_io.seek( m_file, m_nNamePos );
if ( m_bUseIncorrectLISETLength )
{
size = m_nLISETSize - 8;
}
WriteInt( size );
m_io.close( m_file );
}
void OutFileRIFF::HasLISETData( int position )
{
m_bUseIncorrectLISETLength = true;
m_nLISETSize = position;
}
bool OutFileRIFF::WriteInt( int number )
{
if ( !IsValid() )
return false;
m_io.write( &number, sizeof( int ), m_file );
return true;
}
bool OutFileRIFF::WriteData( void *pOutput, int dataSize )
{
if ( !IsValid() )
return false;
m_io.write( pOutput, dataSize, m_file );
return true;
}
int OutFileRIFF::PositionGet( void )
{
if ( !IsValid() )
return 0;
return m_io.tell( m_file );
}
void OutFileRIFF::PositionSet( int position )
{
if ( !IsValid() )
return;
m_io.seek( m_file, position );
}
//-----------------------------------------------------------------------------
// Purpose: Create an iterator for the given file
// Input : &riff - riff file
// size - size of file or sub-chunk
//-----------------------------------------------------------------------------
IterateRIFF::IterateRIFF( InFileRIFF &riff, int size )
: m_riff(riff), m_size(size)
{
if ( !m_riff.RIFFSize() )
{
// bad file, just be an empty iterator
ChunkClear();
return;
}
// get the position and parse a chunk
m_start = riff.PositionGet();
ChunkSetup();
}
//-----------------------------------------------------------------------------
// Purpose: Set up a sub-chunk iterator
// Input : &parent - parent iterator
//-----------------------------------------------------------------------------
IterateRIFF::IterateRIFF( IterateRIFF &parent )
: m_riff(parent.m_riff), m_size(parent.ChunkSize())
{
m_start = parent.ChunkFilePosition();
ChunkSetup();
}
//-----------------------------------------------------------------------------
// Purpose: Parse the chunk at the current file position
// This object will iterate over the sub-chunks of this chunk.
// This makes for easy hierarchical parsing
//-----------------------------------------------------------------------------
void IterateRIFF::ChunkSetup( void )
{
m_chunkPosition = m_riff.PositionGet();
m_chunkName = m_riff.ReadInt();
m_chunkSize = m_riff.ReadInt();
}
//-----------------------------------------------------------------------------
// Purpose: clear chunk setup, ChunkAvailable will return false
//-----------------------------------------------------------------------------
void IterateRIFF::ChunkClear( void )
{
m_chunkSize = -1;
}
//-----------------------------------------------------------------------------
// Purpose: If there are chunks left to read beyond this one, return true
//-----------------------------------------------------------------------------
bool IterateRIFF::ChunkAvailable( void )
{
if ( m_chunkSize != -1 && m_chunkSize < 0x10000000 )
return true;
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Go to the next chunk in the file, return true if there is one.
//-----------------------------------------------------------------------------
bool IterateRIFF::ChunkNext( void )
{
if ( !ChunkAvailable() )
return false;
int nextPos = m_chunkPosition + 8 + m_chunkSize;
// chunks are aligned
nextPos += m_chunkSize & 1;
if ( nextPos >= (m_start + m_size) )
{
ChunkClear();
return false;
}
m_riff.PositionSet( nextPos );
ChunkSetup();
return ChunkAvailable();
}
//-----------------------------------------------------------------------------
// Purpose: get the chunk FOURCC as an int
// Output : unsigned int
//-----------------------------------------------------------------------------
unsigned int IterateRIFF::ChunkName( void )
{
return m_chunkName;
}
//-----------------------------------------------------------------------------
// Purpose: get the size of this chunk
// Output : unsigned int
//-----------------------------------------------------------------------------
unsigned int IterateRIFF::ChunkSize( void )
{
return m_chunkSize;
}
//-----------------------------------------------------------------------------
// Purpose: Read the entire chunk into a buffer
// Input : *pOutput - dest buffer
// Output : int bytes read
//-----------------------------------------------------------------------------
int IterateRIFF::ChunkRead( void *pOutput )
{
return m_riff.ReadData( pOutput, ChunkSize() );
}
//-----------------------------------------------------------------------------
// Purpose: Read a partial chunk (updates file position for subsequent partial reads).
// Input : *pOutput - dest buffer
// dataSize - partial size
// Output : int - bytes read
//-----------------------------------------------------------------------------
int IterateRIFF::ChunkReadPartial( void *pOutput, int dataSize )
{
return m_riff.ReadData( pOutput, dataSize );
}
//-----------------------------------------------------------------------------
// Purpose: Read a 4-byte int
// Output : int - read int
//-----------------------------------------------------------------------------
int IterateRIFF::ChunkReadInt( void )
{
return m_riff.ReadInt();
}
//-----------------------------------------------------------------------------
// Purpose: Used to iterate over an InFileRIFF
//-----------------------------------------------------------------------------
IterateOutputRIFF::IterateOutputRIFF( OutFileRIFF &riff )
: m_riff( riff )
{
if ( !m_riff.IsValid() )
return;
m_start = m_riff.PositionGet();
m_chunkPosition = m_start;
m_chunkStart = -1;
}
IterateOutputRIFF::IterateOutputRIFF( IterateOutputRIFF &parent )
: m_riff(parent.m_riff)
{
m_start = parent.ChunkFilePosition();
m_chunkPosition = m_start;
m_chunkStart = -1;
}
void IterateOutputRIFF::ChunkWrite( unsigned int chunkname, void *pOutput, int size )
{
m_chunkPosition = m_riff.PositionGet();
m_chunkName = chunkname;
m_chunkSize = size;
m_riff.WriteInt( chunkname );
m_riff.WriteInt( size );
m_riff.WriteData( pOutput, size );
m_chunkPosition = m_riff.PositionGet();
m_chunkPosition += m_chunkPosition & 1;
m_riff.PositionSet( m_chunkPosition );
m_chunkStart = -1;
}
void IterateOutputRIFF::ChunkWriteInt( int number )
{
m_riff.WriteInt( number );
}
void IterateOutputRIFF::ChunkWriteData( void *pOutput, int size )
{
m_riff.WriteData( pOutput, size );
}
void IterateOutputRIFF::ChunkFinish( void )
{
Assert( m_chunkStart != -1 );
m_chunkPosition = m_riff.PositionGet();
int size = m_chunkPosition - m_chunkStart - 8;
m_chunkPosition += m_chunkPosition & 1;
m_riff.PositionSet( m_chunkStart + sizeof( int ) );
m_riff.WriteInt( size );
m_riff.PositionSet( m_chunkPosition );
m_chunkStart = -1;
}
void IterateOutputRIFF::ChunkStart( unsigned int chunkname )
{
Assert( m_chunkStart == -1 );
m_chunkStart = m_riff.PositionGet();
m_riff.WriteInt( chunkname );
m_riff.WriteInt( 0 );
}
void IterateOutputRIFF::ChunkSetPosition( int position )
{
m_riff.PositionSet( position );
}
unsigned int IterateOutputRIFF::ChunkGetPosition( void )
{
return m_riff.PositionGet();
}
void IterateOutputRIFF::CopyChunkData( IterateRIFF& input )
{
if ( input.ChunkSize() > 0 )
{
char *buffer = new char[ input.ChunkSize() ];
Assert( buffer );
input.ChunkRead( buffer );
// Don't copy/write the name or size, just the data itself
ChunkWriteData( buffer, input.ChunkSize() );
delete[] buffer;
}
}
void IterateOutputRIFF::SetLISETData( int position )
{
m_riff.HasLISETData( position );
}

237
tier2/soundutils.cpp Normal file
View File

@ -0,0 +1,237 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Helper methods + classes for sound
//
//===========================================================================//
#include "tier2/soundutils.h"
#include "tier2/riff.h"
#include "tier2/tier2.h"
#include "filesystem.h"
#ifdef IS_WINDOWS_PC
#include <windows.h> // WAVEFORMATEX, WAVEFORMAT and ADPCM WAVEFORMAT!!!
#include <mmreg.h>
#else
#ifdef _X360
#include "xbox/xbox_win32stubs.h" // WAVEFORMATEX, WAVEFORMAT and ADPCM WAVEFORMAT!!!
#endif
#endif
//-----------------------------------------------------------------------------
// RIFF reader/writers that use the file system
//-----------------------------------------------------------------------------
class CFSIOReadBinary : public IFileReadBinary
{
public:
// inherited from IFileReadBinary
virtual int open( const char *pFileName );
virtual int read( void *pOutput, int size, int file );
virtual void seek( int file, int pos );
virtual unsigned int tell( int file );
virtual unsigned int size( int file );
virtual void close( int file );
};
class CFSIOWriteBinary : public IFileWriteBinary
{
public:
virtual int create( const char *pFileName );
virtual int write( void *pData, int size, int file );
virtual void close( int file );
virtual void seek( int file, int pos );
virtual unsigned int tell( int file );
};
//-----------------------------------------------------------------------------
// Singletons
//-----------------------------------------------------------------------------
static CFSIOReadBinary s_FSIoIn;
static CFSIOWriteBinary s_FSIoOut;
IFileReadBinary *g_pFSIOReadBinary = &s_FSIoIn;
IFileWriteBinary *g_pFSIOWriteBinary = &s_FSIoOut;
//-----------------------------------------------------------------------------
// RIFF reader that use the file system
//-----------------------------------------------------------------------------
int CFSIOReadBinary::open( const char *pFileName )
{
return (int)g_pFullFileSystem->Open( pFileName, "rb" );
}
int CFSIOReadBinary::read( void *pOutput, int size, int file )
{
if ( !file )
return 0;
return g_pFullFileSystem->Read( pOutput, size, (FileHandle_t)file );
}
void CFSIOReadBinary::seek( int file, int pos )
{
if ( !file )
return;
g_pFullFileSystem->Seek( (FileHandle_t)file, pos, FILESYSTEM_SEEK_HEAD );
}
unsigned int CFSIOReadBinary::tell( int file )
{
if ( !file )
return 0;
return g_pFullFileSystem->Tell( (FileHandle_t)file );
}
unsigned int CFSIOReadBinary::size( int file )
{
if ( !file )
return 0;
return g_pFullFileSystem->Size( (FileHandle_t)file );
}
void CFSIOReadBinary::close( int file )
{
if ( !file )
return;
g_pFullFileSystem->Close( (FileHandle_t)file );
}
//-----------------------------------------------------------------------------
// RIFF writer that use the file system
//-----------------------------------------------------------------------------
int CFSIOWriteBinary::create( const char *pFileName )
{
g_pFullFileSystem->SetFileWritable( pFileName, true );
return (int)g_pFullFileSystem->Open( pFileName, "wb" );
}
int CFSIOWriteBinary::write( void *pData, int size, int file )
{
return g_pFullFileSystem->Write( pData, size, (FileHandle_t)file );
}
void CFSIOWriteBinary::close( int file )
{
g_pFullFileSystem->Close( (FileHandle_t)file );
}
void CFSIOWriteBinary::seek( int file, int pos )
{
g_pFullFileSystem->Seek( (FileHandle_t)file, pos, FILESYSTEM_SEEK_HEAD );
}
unsigned int CFSIOWriteBinary::tell( int file )
{
return g_pFullFileSystem->Tell( (FileHandle_t)file );
}
#ifndef POSIX
//-----------------------------------------------------------------------------
// Returns the duration of a wav file
//-----------------------------------------------------------------------------
float GetWavSoundDuration( const char *pWavFile )
{
InFileRIFF riff( pWavFile, *g_pFSIOReadBinary );
// UNDONE: Don't use printf to handle errors
if ( riff.RIFFName() != RIFF_WAVE )
return 0.0f;
int nDataSize = 0;
// set up the iterator for the whole file (root RIFF is a chunk)
IterateRIFF walk( riff, riff.RIFFSize() );
// This chunk must be first as it contains the wave's format
// break out when we've parsed it
char pFormatBuffer[ 1024 ];
int nFormatSize;
bool bFound = false;
for ( ; walk.ChunkAvailable( ); walk.ChunkNext() )
{
switch ( walk.ChunkName() )
{
case WAVE_FMT:
bFound = true;
if ( walk.ChunkSize() > sizeof(pFormatBuffer) )
{
Warning( "oops, format tag too big!!!" );
return 0.0f;
}
nFormatSize = walk.ChunkSize();
walk.ChunkRead( pFormatBuffer );
break;
case WAVE_DATA:
nDataSize += walk.ChunkSize();
break;
}
}
if ( !bFound )
return 0.0f;
const WAVEFORMATEX *pHeader = (const WAVEFORMATEX *)pFormatBuffer;
int format = pHeader->wFormatTag;
int nBits = pHeader->wBitsPerSample;
int nRate = pHeader->nSamplesPerSec;
int nChannels = pHeader->nChannels;
int nSampleSize = ( nBits * nChannels ) / 8;
// this can never be zero -- other functions divide by this.
// This should never happen, but avoid crashing
if ( nSampleSize <= 0 )
{
nSampleSize = 1;
}
int nSampleCount = 0;
float flTrueSampleSize = nSampleSize;
if ( format == WAVE_FORMAT_ADPCM )
{
nSampleSize = 1;
ADPCMWAVEFORMAT *pFormat = (ADPCMWAVEFORMAT *)pFormatBuffer;
int blockSize = ((pFormat->wSamplesPerBlock - 2) * pFormat->wfx.nChannels ) / 2;
blockSize += 7 * pFormat->wfx.nChannels;
int blockCount = nSampleCount / blockSize;
int blockRem = nSampleCount % blockSize;
// total samples in complete blocks
nSampleCount = blockCount * pFormat->wSamplesPerBlock;
// add remaining in a short block
if ( blockRem )
{
nSampleCount += pFormat->wSamplesPerBlock - (((blockSize - blockRem) * 2) / nChannels);
}
flTrueSampleSize = 0.5f;
}
else
{
nSampleCount = nDataSize / nSampleSize;
}
float flDuration = (float)nSampleCount / (float)nRate;
return flDuration;
}
#endif

117
tier2/tier2.cpp Normal file
View File

@ -0,0 +1,117 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A higher level link library for general use in the game and tools.
//
//===========================================================================//
#include <tier2/tier2.h>
#include "tier0/dbg.h"
#include "filesystem.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/imaterialsystemhardwareconfig.h"
#include "materialsystem/IColorCorrection.h"
#include "materialsystem/idebugtextureinfo.h"
#include "materialsystem/ivballoctracker.h"
#include "inputsystem/iinputsystem.h"
#include "networksystem/inetworksystem.h"
#include "p4lib/ip4.h"
#include "mdllib/mdllib.h"
#include "filesystem/IQueuedLoader.h"
//-----------------------------------------------------------------------------
// These tier2 libraries must be set by any users of this library.
// They can be set by calling ConnectTier2Libraries or InitDefaultFileSystem.
// It is hoped that setting this, and using this library will be the common mechanism for
// allowing link libraries to access tier2 library interfaces
//-----------------------------------------------------------------------------
IFileSystem *g_pFullFileSystem = 0;
IMaterialSystem *materials = 0;
IMaterialSystem *g_pMaterialSystem = 0;
IInputSystem *g_pInputSystem = 0;
INetworkSystem *g_pNetworkSystem = 0;
IMaterialSystemHardwareConfig *g_pMaterialSystemHardwareConfig = 0;
IDebugTextureInfo *g_pMaterialSystemDebugTextureInfo = 0;
IVBAllocTracker *g_VBAllocTracker = 0;
IColorCorrectionSystem *colorcorrection = 0;
IP4 *p4 = 0;
IMdlLib *mdllib = 0;
IQueuedLoader *g_pQueuedLoader = 0;
//-----------------------------------------------------------------------------
// Call this to connect to all tier 2 libraries.
// It's up to the caller to check the globals it cares about to see if ones are missing
//-----------------------------------------------------------------------------
void ConnectTier2Libraries( CreateInterfaceFn *pFactoryList, int nFactoryCount )
{
// Don't connect twice..
Assert( !g_pFullFileSystem && !materials && !g_pInputSystem && !g_pNetworkSystem &&
!p4 && !mdllib && !g_pMaterialSystemDebugTextureInfo && !g_VBAllocTracker &&
!g_pMaterialSystemHardwareConfig && !g_pQueuedLoader );
for ( int i = 0; i < nFactoryCount; ++i )
{
if ( !g_pFullFileSystem )
{
g_pFullFileSystem = ( IFileSystem * )pFactoryList[i]( FILESYSTEM_INTERFACE_VERSION, NULL );
}
if ( !materials )
{
g_pMaterialSystem = materials = ( IMaterialSystem * )pFactoryList[i]( MATERIAL_SYSTEM_INTERFACE_VERSION, NULL );
}
if ( !g_pInputSystem )
{
g_pInputSystem = ( IInputSystem * )pFactoryList[i]( INPUTSYSTEM_INTERFACE_VERSION, NULL );
}
if ( !g_pNetworkSystem )
{
g_pNetworkSystem = ( INetworkSystem * )pFactoryList[i]( NETWORKSYSTEM_INTERFACE_VERSION, NULL );
}
if ( !g_pMaterialSystemHardwareConfig )
{
g_pMaterialSystemHardwareConfig = ( IMaterialSystemHardwareConfig * )pFactoryList[i]( MATERIALSYSTEM_HARDWARECONFIG_INTERFACE_VERSION, NULL );
}
if ( !g_pMaterialSystemDebugTextureInfo )
{
g_pMaterialSystemDebugTextureInfo = (IDebugTextureInfo*)pFactoryList[i]( DEBUG_TEXTURE_INFO_VERSION, 0 );
}
if ( !g_VBAllocTracker )
{
g_VBAllocTracker = (IVBAllocTracker*)pFactoryList[i]( VB_ALLOC_TRACKER_INTERFACE_VERSION, 0 );
}
if ( !colorcorrection )
{
colorcorrection = ( IColorCorrectionSystem * )pFactoryList[i]( COLORCORRECTION_INTERFACE_VERSION, NULL );
}
if ( !p4 )
{
p4 = ( IP4 * )pFactoryList[i]( P4_INTERFACE_VERSION, NULL );
}
if ( !mdllib )
{
mdllib = ( IMdlLib * )pFactoryList[i]( MDLLIB_INTERFACE_VERSION, NULL );
}
if ( !g_pQueuedLoader )
{
g_pQueuedLoader = (IQueuedLoader *)pFactoryList[i]( QUEUEDLOADER_INTERFACE_VERSION, NULL );
}
}
}
void DisconnectTier2Libraries()
{
g_pFullFileSystem = 0;
materials = g_pMaterialSystem = 0;
g_pMaterialSystemHardwareConfig = 0;
g_pMaterialSystemDebugTextureInfo = 0;
g_pInputSystem = 0;
g_pNetworkSystem = 0;
colorcorrection = 0;
p4 = 0;
mdllib = 0;
g_pQueuedLoader = 0;
}

58
tier2/tier2.vpc Normal file
View File

@ -0,0 +1,58 @@
//-----------------------------------------------------------------------------
// TIER2.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$macro SRCDIR ".."
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE;$SRCDIR\public\tier2"
}
}
$Project "tier2"
{
$Folder "Source Files"
{
$File "beamsegdraw.cpp"
$File "defaultfilesystem.cpp"
$File "dmconnect.cpp"
$file "fileutils.cpp"
$File "keybindings.cpp"
$File "$SRCDIR\public\map_utils.cpp"
$File "$SRCDIR\public\materialsystem\MaterialSystemUtil.cpp"
$File "camerautils.cpp"
$File "meshutils.cpp"
$File "p4helpers.cpp"
$File "renderutils.cpp"
$File "riff.cpp"
$File "soundutils.cpp"
$File "tier2.cpp"
$File "util_init.cpp"
$File "utlstreambuffer.cpp"
$File "vconfig.cpp"
$File "keyvaluesmacros.cpp"
}
$Folder "Public Header Files"
{
$File "$SRCDIR\public\tier2\beamsegdraw.h"
$File "$SRCDIR\public\tier2\fileutils.h"
$File "$SRCDIR\public\tier2\camerautils.h"
$File "$SRCDIR\public\tier2\meshutils.h"
$File "$SRCDIR\public\tier2\keybindings.h"
$File "$SRCDIR\public\tier2\renderutils.h"
$File "$SRCDIR\public\tier2\riff.h"
$File "$SRCDIR\public\tier2\soundutils.h"
$File "$SRCDIR\public\tier2\tier2.h"
$File "$SRCDIR\public\tier2\utlstreambuffer.h"
$File "$SRCDIR\public\tier2\vconfig.h"
$File "$SRCDIR\public\tier2\keyvaluesmacros.h"
}
}

50
tier2/util_init.cpp Normal file
View File

@ -0,0 +1,50 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: perform initialization needed in most command line programs
//
//===================================================================================-=//
#include <tier0/platform.h>
#include <tier2/tier2.h>
#include <mathlib/mathlib.h>
#include <tier0/icommandline.h>
#include "tier0/memalloc.h"
#include "tier0/progressbar.h"
#include "tier1/strtools.h"
static void PrintFReportHandler(char const *job_name, int total_units_to_do, int n_units_completed)
{
static bool work_in_progress=false;
static char LastJobName[1024];
if ( Q_strncmp( LastJobName, job_name, sizeof( LastJobName ) ) )
{
if ( work_in_progress )
printf("..done\n");
Q_strncpy( LastJobName, job_name, sizeof( LastJobName ) );
}
if ( (total_units_to_do > 0 ) && (total_units_to_do >= n_units_completed) )
{
int percent_done=(100*n_units_completed)/total_units_to_do;
printf("\r%s : %d%%",LastJobName, percent_done );
work_in_progress = true;
}
else
{
printf("%s\n",LastJobName);
work_in_progress = false;
}
}
void InitCommandLineProgram( int argc, char **argv )
{
MathLib_Init( 1,1,1,0,false,true,true,true);
CommandLine()->CreateCmdLine( argc, argv );
InitDefaultFileSystem();
InstallProgressReportHandler( PrintFReportHandler );
// By default, command line programs should not use the new assert dialog,
// and any asserts should be fatal, unless we are being debugged
if ( !Plat_IsInDebugSession() )
SpewOutputFunc( DefaultSpewFuncAbortOnAsserts );
}

386
tier2/utlstreambuffer.cpp Normal file
View File

@ -0,0 +1,386 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
// Serialization/unserialization buffer
//=============================================================================//
#include "tier2/utlstreambuffer.h"
#include "tier2/tier2.h"
#include "filesystem.h"
//-----------------------------------------------------------------------------
// default stream chunk size
//-----------------------------------------------------------------------------
enum
{
DEFAULT_STREAM_CHUNK_SIZE = 16 * 1024
};
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CUtlStreamBuffer::CUtlStreamBuffer( ) : BaseClass( DEFAULT_STREAM_CHUNK_SIZE, DEFAULT_STREAM_CHUNK_SIZE, 0 )
{
SetUtlBufferOverflowFuncs( &CUtlStreamBuffer::StreamGetOverflow, &CUtlStreamBuffer::StreamPutOverflow );
m_hFileHandle = FILESYSTEM_INVALID_HANDLE;
m_pFileName = NULL;
m_pPath = NULL;
}
CUtlStreamBuffer::CUtlStreamBuffer( const char *pFileName, const char *pPath, int nFlags, bool bDelayOpen ) :
BaseClass( DEFAULT_STREAM_CHUNK_SIZE, DEFAULT_STREAM_CHUNK_SIZE, nFlags )
{
SetUtlBufferOverflowFuncs( &CUtlStreamBuffer::StreamGetOverflow, &CUtlStreamBuffer::StreamPutOverflow );
if ( bDelayOpen )
{
m_pFileName = V_strdup( pFileName );
if ( pPath )
{
int nPathLen = Q_strlen( pPath );
m_pPath = new char[ nPathLen + 1 ];
Q_strcpy( m_pPath, pPath );
}
else
{
m_pPath = new char[ 1 ];
m_pPath[0] = 0;
}
m_hFileHandle = FILESYSTEM_INVALID_HANDLE;
}
else
{
m_pFileName = NULL;
m_pPath = NULL;
m_hFileHandle = OpenFile( pFileName, pPath );
if ( m_hFileHandle == FILESYSTEM_INVALID_HANDLE )
{
return;
}
}
if ( IsReadOnly() )
{
// NOTE: MaxPut may not actually be this exact size for text files;
// it could be slightly less owing to the /r/n -> /n conversion
m_nMaxPut = g_pFullFileSystem->Size( m_hFileHandle );
// Read in the first bytes of the file
if ( Size() > 0 )
{
int nSizeToRead = min( Size(), m_nMaxPut );
ReadBytesFromFile( nSizeToRead, 0 );
}
}
}
void CUtlStreamBuffer::Close()
{
if ( !IsReadOnly() )
{
// Write the final bytes
int nBytesToWrite = TellPut() - m_nOffset;
if ( nBytesToWrite > 0 )
{
if ( ( m_hFileHandle == FILESYSTEM_INVALID_HANDLE ) && m_pFileName )
{
m_hFileHandle = OpenFile( m_pFileName, m_pPath );
if( m_hFileHandle == FILESYSTEM_INVALID_HANDLE )
{
Error( "CUtlStreamBuffer::Close() Unable to open file %s!\n", m_pFileName );
}
}
if ( m_hFileHandle != FILESYSTEM_INVALID_HANDLE )
{
if ( g_pFullFileSystem )
{
int nBytesWritten = g_pFullFileSystem->Write( Base(), nBytesToWrite, m_hFileHandle );
if( nBytesWritten != nBytesToWrite )
{
Error( "CUtlStreamBuffer::Close() Write %s failed %d != %d.\n", m_pFileName, nBytesWritten, nBytesToWrite );
}
}
}
}
}
if ( m_hFileHandle != FILESYSTEM_INVALID_HANDLE )
{
if ( g_pFullFileSystem )
g_pFullFileSystem->Close( m_hFileHandle );
m_hFileHandle = FILESYSTEM_INVALID_HANDLE;
}
if ( m_pFileName )
{
delete[] m_pFileName;
m_pFileName = NULL;
}
if ( m_pPath )
{
delete[] m_pPath;
m_pPath = NULL;
}
m_Error = 0;
}
CUtlStreamBuffer::~CUtlStreamBuffer()
{
Close();
}
//-----------------------------------------------------------------------------
// Open the file. normally done in constructor
//-----------------------------------------------------------------------------
void CUtlStreamBuffer::Open( const char *pFileName, const char *pPath, int nFlags )
{
if ( IsOpen() )
{
Close();
}
m_Get = 0;
m_Put = 0;
m_nTab = 0;
m_nOffset = 0;
m_Flags = nFlags;
m_hFileHandle = OpenFile( pFileName, pPath );
if ( m_hFileHandle == FILESYSTEM_INVALID_HANDLE )
return;
if ( IsReadOnly() )
{
// NOTE: MaxPut may not actually be this exact size for text files;
// it could be slightly less owing to the /r/n -> /n conversion
m_nMaxPut = g_pFullFileSystem->Size( m_hFileHandle );
// Read in the first bytes of the file
if ( Size() > 0 )
{
int nSizeToRead = min( Size(), m_nMaxPut );
ReadBytesFromFile( nSizeToRead, 0 );
}
}
else
{
if ( m_Memory.NumAllocated() != 0 )
{
m_nMaxPut = -1;
AddNullTermination();
}
else
{
m_nMaxPut = 0;
}
}
}
//-----------------------------------------------------------------------------
// Is the file open?
//-----------------------------------------------------------------------------
bool CUtlStreamBuffer::IsOpen() const
{
if ( m_hFileHandle != FILESYSTEM_INVALID_HANDLE )
return true;
// Delayed open case
return ( m_pFileName != 0 );
}
//-----------------------------------------------------------------------------
// Grow allocation size to fit requested size
//-----------------------------------------------------------------------------
void CUtlStreamBuffer::GrowAllocatedSize( int nSize )
{
int nNewSize = Size();
if ( nNewSize < nSize + 1 )
{
while ( nNewSize < nSize + 1 )
{
nNewSize += DEFAULT_STREAM_CHUNK_SIZE;
}
m_Memory.Grow( nNewSize - Size() );
}
}
//-----------------------------------------------------------------------------
// Load up more of the stream when we overflow
//-----------------------------------------------------------------------------
bool CUtlStreamBuffer::StreamPutOverflow( int nSize )
{
if ( !IsValid() || IsReadOnly() )
return false;
// Make sure the allocated size is at least as big as the requested size
if ( nSize > 0 )
{
GrowAllocatedSize( nSize + 2 );
}
// Don't write the last byte (for NULL termination logic to work)
int nBytesToWrite = TellPut() - m_nOffset - 1;
if ( ( nBytesToWrite > 0 ) || ( nSize < 0 ) )
{
if ( m_hFileHandle == FILESYSTEM_INVALID_HANDLE )
{
m_hFileHandle = OpenFile( m_pFileName, m_pPath );
if( m_hFileHandle == FILESYSTEM_INVALID_HANDLE )
return false;
}
}
if ( nBytesToWrite > 0 )
{
int nBytesWritten = g_pFullFileSystem->Write( Base(), nBytesToWrite, m_hFileHandle );
if ( nBytesWritten != nBytesToWrite )
{
m_Error |= FILE_WRITE_ERROR;
return false;
}
// This is necessary to deal with auto-NULL terminiation
m_Memory[0] = *(unsigned char*)PeekPut( -1 );
if ( TellPut() < Size() )
{
m_Memory[1] = *(unsigned char*)PeekPut( );
}
m_nOffset = TellPut() - 1;
}
if ( nSize < 0 )
{
m_nOffset = -nSize-1;
g_pFullFileSystem->Seek( m_hFileHandle, m_nOffset, FILESYSTEM_SEEK_HEAD );
}
return true;
}
//-----------------------------------------------------------------------------
// Reads bytes from the file; fixes up maxput if necessary and null terminates
//-----------------------------------------------------------------------------
int CUtlStreamBuffer::ReadBytesFromFile( int nBytesToRead, int nReadOffset )
{
if ( m_hFileHandle == FILESYSTEM_INVALID_HANDLE )
{
if ( !m_pFileName )
{
Warning( "File has not been opened!\n" );
Assert(0);
return 0;
}
m_hFileHandle = OpenFile( m_pFileName, m_pPath );
if ( m_hFileHandle == FILESYSTEM_INVALID_HANDLE )
{
Error( "Unable to read file %s!\n", m_pFileName );
return 0;
}
if ( m_nOffset != 0 )
{
g_pFullFileSystem->Seek( m_hFileHandle, m_nOffset, FILESYSTEM_SEEK_HEAD );
}
}
char *pReadPoint = (char*)Base() + nReadOffset;
int nBytesRead = g_pFullFileSystem->Read( pReadPoint, nBytesToRead, m_hFileHandle );
if ( nBytesRead != nBytesToRead )
{
// Since max put is a guess at the start,
// we need to shrink it based on the actual # read
if ( m_nMaxPut > TellGet() + nReadOffset + nBytesRead )
{
m_nMaxPut = TellGet() + nReadOffset + nBytesRead;
}
}
if ( nReadOffset + nBytesRead < Size() )
{
// This is necessary to deal with auto-NULL terminiation
pReadPoint[nBytesRead] = 0;
}
return nBytesRead;
}
//-----------------------------------------------------------------------------
// Load up more of the stream when we overflow
//-----------------------------------------------------------------------------
bool CUtlStreamBuffer::StreamGetOverflow( int nSize )
{
if ( !IsValid() || !IsReadOnly() )
return false;
// Shift the unread bytes down
// NOTE: Can't use the partial overlap path if we're seeking. We'll
// get negative sizes passed in if we're seeking.
int nUnreadBytes;
bool bHasPartialOverlap = ( nSize >= 0 ) && ( TellGet() >= m_nOffset ) && ( TellGet() <= m_nOffset + Size() );
if ( bHasPartialOverlap )
{
nUnreadBytes = Size() - ( TellGet() - m_nOffset );
if ( ( TellGet() != m_nOffset ) && ( nUnreadBytes > 0 ) )
{
memmove( Base(), (const char*)Base() + TellGet() - m_nOffset, nUnreadBytes );
}
}
else
{
m_nOffset = TellGet();
g_pFullFileSystem->Seek( m_hFileHandle, m_nOffset, FILESYSTEM_SEEK_HEAD );
nUnreadBytes = 0;
}
// Make sure the allocated size is at least as big as the requested size
if ( nSize > 0 )
{
GrowAllocatedSize( nSize );
}
int nBytesToRead = Size() - nUnreadBytes;
int nBytesRead = ReadBytesFromFile( nBytesToRead, nUnreadBytes );
if ( nBytesRead == 0 )
return false;
m_nOffset = TellGet();
return ( nBytesRead + nUnreadBytes >= nSize );
}
//-----------------------------------------------------------------------------
// open file unless already failed to open
//-----------------------------------------------------------------------------
FileHandle_t CUtlStreamBuffer::OpenFile( const char *pFileName, const char *pPath )
{
if ( m_Error & FILE_OPEN_ERROR )
return FILESYSTEM_INVALID_HANDLE;
char openflags[ 3 ] = "xx";
openflags[ 0 ] = IsReadOnly() ? 'r' : 'w';
openflags[ 1 ] = IsText() && !ContainsCRLF() ? 't' : 'b';
FileHandle_t fh = g_pFullFileSystem->Open( pFileName, openflags, pPath );
if( fh == FILESYSTEM_INVALID_HANDLE )
{
m_Error |= FILE_OPEN_ERROR;
}
return fh;
}

149
tier2/vconfig.cpp Normal file
View File

@ -0,0 +1,149 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Utilities for setting vproject settings
//
//===========================================================================//
#ifdef _WIN32
#if !defined( _X360 )
#include <windows.h>
#endif
#include <direct.h>
#include <io.h> // _chmod
#include <process.h>
#endif
#if defined( _X360 )
#include "xbox/xbox_win32stubs.h"
#endif
#include "vconfig.h"
#ifdef _WIN32
//-----------------------------------------------------------------------------
// Purpose: Returns the string value of a registry key
// Input : *pName - name of the subKey to read
// *pReturn - string buffer to receive read string
// size - size of specified buffer
//-----------------------------------------------------------------------------
bool GetVConfigRegistrySetting( const char *pName, char *pReturn, int size )
{
// Open the key
HKEY hregkey;
// Changed to HKEY_CURRENT_USER from HKEY_LOCAL_MACHINE
if ( RegOpenKeyEx( HKEY_CURRENT_USER, VPROJECT_REG_KEY, 0, KEY_QUERY_VALUE, &hregkey ) != ERROR_SUCCESS )
return false;
// Get the value
DWORD dwSize = size;
if ( RegQueryValueEx( hregkey, pName, NULL, NULL,(LPBYTE) pReturn, &dwSize ) != ERROR_SUCCESS )
return false;
// Close the key
RegCloseKey( hregkey );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Sends a global system message to alert programs to a changed environment variable
//-----------------------------------------------------------------------------
void NotifyVConfigRegistrySettingChanged( void )
{
DWORD_PTR dwReturnValue = 0;
// Propagate changes so that environment variables takes immediate effect!
SendMessageTimeout( HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) "Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue );
}
//-----------------------------------------------------------------------------
// Purpose: Set the registry entry to a string value, under the given subKey
// Input : *pName - name of the subKey to set
// *pValue - string value
//-----------------------------------------------------------------------------
void SetVConfigRegistrySetting( const char *pName, const char *pValue, bool bNotify )
{
HKEY hregkey;
// Changed to HKEY_CURRENT_USER from HKEY_LOCAL_MACHINE
// Open the key
if ( RegCreateKeyEx(
HKEY_CURRENT_USER, // base key
VPROJECT_REG_KEY, // subkey
0, // reserved
0, // lpClass
0, // options
(REGSAM)KEY_ALL_ACCESS, // access desired
NULL, // security attributes
&hregkey, // result
NULL // tells if it created the key or not (which we don't care)
) != ERROR_SUCCESS )
{
return;
}
// Set the value to the string passed in
int nType = strchr( pValue, '%' ) ? REG_EXPAND_SZ : REG_SZ;
RegSetValueEx( hregkey, pName, 0, nType, (const unsigned char *)pValue, (int) strlen(pValue) );
// Notify other programs
if ( bNotify )
{
NotifyVConfigRegistrySettingChanged();
}
// Close the key
RegCloseKey( hregkey );
}
//-----------------------------------------------------------------------------
// Purpose: Removes the obsolete user keyvalue
// Input : *pName - name of the subKey to set
// *pValue - string value
//-----------------------------------------------------------------------------
bool RemoveObsoleteVConfigRegistrySetting( const char *pValueName, char *pOldValue, int size )
{
// Open the key
HKEY hregkey;
if ( RegOpenKeyEx( HKEY_CURRENT_USER, "Environment", 0, (REGSAM)KEY_ALL_ACCESS, &hregkey ) != ERROR_SUCCESS )
return false;
// Return the old state if they've requested it
if ( pOldValue != NULL )
{
DWORD dwSize = size;
// Get the value
if ( RegQueryValueEx( hregkey, pValueName, NULL, NULL,(LPBYTE) pOldValue, &dwSize ) != ERROR_SUCCESS )
return false;
}
// Remove the value
if ( RegDeleteValue( hregkey, pValueName ) != ERROR_SUCCESS )
return false;
// Close the key
RegCloseKey( hregkey );
// Notify other programs
NotifyVConfigRegistrySettingChanged();
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Take a user-defined environment variable and swap it out for the internally used one
//-----------------------------------------------------------------------------
bool ConvertObsoleteVConfigRegistrySetting( const char *pValueName )
{
char szValue[MAX_PATH];
if ( RemoveObsoleteVConfigRegistrySetting( pValueName, szValue, sizeof( szValue ) ) )
{
// Set it up the correct way
SetVConfigRegistrySetting( pValueName, szValue );
return true;
}
return false;
}
#endif