This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

View File

@@ -0,0 +1,669 @@
//===== Copyright <20> 2005-2006, Valve Corporation, All rights reserved. ======//
//
// Purpose: build a sheet data file and a large image out of multiple images
//
//===========================================================================//
#include "amalg_texture.h"
#include "tier0/platform.h"
#include "tier0/progressbar.h"
#include "mathlib/mathlib.h"
#include "filesystem.h"
#include "tier1/strtools.h"
#include "bitmap/floatbitmap.h"
#include "tier2/fileutils.h"
#include "stdlib.h"
#include "tier0/dbg.h"
static int GetChannelIndexFromChar( char c )
{
// r->0 b->1 g->2 a->3 else -1
static char s_ChannelIDs[]="rgba";
char const *pChanChar = strchr( s_ChannelIDs, c );
if ( ! pChanChar )
{
printf( " bad channel name '%c'\n", c );
return -1;
}
else
{
return pChanChar - s_ChannelIDs;
}
}
static void ZeroChannel( FloatBitMap_t *newBitmap, FloatBitMap_t *pBitmap, int nDestChannel )
{
for ( int y = 0; y < newBitmap->NumRows(); y++ )
{
for ( int x = 0; x < newBitmap->NumCols(); x++ )
{
pBitmap->Pixel( x, y, nDestChannel ) = 0;
}
}
}
static void CopyChannel( FloatBitMap_t *newBitmap, FloatBitMap_t *pBitmap, int nSrcChannel, int nDestChannel )
{
for ( int y = 0; y < newBitmap->NumRows(); y++ )
{
for ( int x = 0; x < newBitmap->NumCols(); x++ )
{
pBitmap->Pixel( x, y, nDestChannel ) = newBitmap->Pixel( x, y, nSrcChannel );
}
}
}
static FloatBitMap_t *CreateFloatBitmap( const char * fname )
{
if ( strchr( fname, ',' ) == NULL )
{
char pFileFullPath[ MAX_PATH ];
if ( !GenerateFullPath( fname, NULL, pFileFullPath, sizeof( pFileFullPath ) ) )
{
Warning( "CDataModel: Unable to generate full path for file %s\n", fname );
return false;
}
return new FloatBitMap_t( pFileFullPath );
}
// parse extended specifications
CUtlVector<char *> Images;
V_SplitString( fname, ",", Images );
FloatBitMap_t *pBitmap = NULL;
// now, process bitmaps, performing copy operations specified by {} syntax
for( int i = 0; i < Images.Count(); i++ )
{
char fnamebuf[MAX_PATH];
strcpy( fnamebuf, Images[i] );
char * pBrace=strchr( fnamebuf, '{' );
if ( pBrace )
{
*pBrace = 0; // null it
pBrace++; // point at control specifier
char *pEndBrace = strchr( pBrace, '}' );
if ( ! pEndBrace )
{
printf( "bad extended bitmap synax (no close brace) - %s \n", Images[i] );
}
}
FloatBitMap_t newBitmap( fnamebuf );
if ( !pBitmap )
{
// first image sets size
pBitmap = new FloatBitMap_t( &newBitmap );
}
// now, process operation specifiers of the form "{chan=chan}" or "{chan=0}"
if ( pBrace && ( pBrace[1] == '=' ) )
{
int nDstChan = GetChannelIndexFromChar( pBrace[0] );
if ( nDstChan != -1 )
{
if ( pBrace[2] == '0' )
{
// zero the channel
ZeroChannel( &newBitmap, pBitmap, nDstChan );
}
else
{
int nSrcChan = GetChannelIndexFromChar( pBrace[2] );
if ( nSrcChan != -1 )
{
// perform the channel copy
CopyChannel( &newBitmap, pBitmap, nSrcChan, nDstChan );
}
}
}
}
}
return pBitmap;
}
CAmalgamatedTexture::CAmalgamatedTexture()
{
m_ePackingMode = PCKM_FLAT;
m_pCurSequence = NULL;
}
void CAmalgamatedTexture::Init( const char *pShtFileName )
{
m_pShtFile = pShtFileName;
}
void CAmalgamatedTexture::SetCurrentSequenceClamp( bool bState )
{
if ( m_pCurSequence )
{
m_pCurSequence->m_Clamp = bState;
}
}
int CAmalgamatedTexture::GetPackingMode()
{
return m_ePackingMode;
}
void CAmalgamatedTexture::SetPackingMode( int eMode )
{
// Assign the packing mode read in to member var.
if ( !m_Sequences.Count() )
{
m_ePackingMode = eMode;
}
else if ( m_ePackingMode != eMode )
{
// Allow special changes:
// flat -> rgb+a
if ( m_ePackingMode == PCKM_FLAT && eMode == PCKM_RGB_A )
{
m_ePackingMode = eMode;
}
// everything else
else
{
printf( "*** line error: incompatible packmode change when %d sequences already defined!\n", m_Sequences.Count() );
//printf( "*** line %d: incompatible packmode change when %d sequences already defined!\n", m_NumActualLinesRead, m_Sequences.Count() );
exit( -1 );
}
}
}
void CAmalgamatedTexture::CreateNewSequence( int sequenceNumber, int mode )
{
m_pCurSequence = new Sequence;
m_pCurSequence->m_nSequenceNumber = sequenceNumber;
SetSequenceType( mode );
m_Sequences.AddToTail( m_pCurSequence );
}
void CAmalgamatedTexture::ValidateSequenceType( int eMode, char *word )
{
switch ( m_ePackingMode )
{
case PCKM_FLAT:
switch ( eMode )
{
case SQM_RGBA:
break;
default:
{
printf( "*** line error: invalid sequence type '%s', packing 'flat' allows only 'sequence-rgba'!\n", word );
//printf( "*** line %d: invalid sequence type '%s', packing 'flat' allows only 'sequence-rgba'!\n", m_NumActualLinesRead, word );
exit( -1 );
}
}
break;
case PCKM_RGB_A:
switch ( eMode )
{
case SQM_RGB:
case SQM_ALPHA:
break;
default:
{
//printf( "*** line %d: invalid sequence type '%s', packing 'rgb+a' allows only 'sequence-rgb' or 'sequence-a'!\n", m_NumActualLinesRead, word );
exit( -1 );
}
}
break;
}
}
int CAmalgamatedTexture::GetSequenceType()
{
return m_pCurSequence->m_eMode;
}
void CAmalgamatedTexture::SetSequenceType( int eMode )
{
m_pCurSequence->m_eMode = eMode;
}
bool CAmalgamatedTexture::CurrentSequenceExists()
{
return m_pCurSequence != NULL;
}
// Validate that frame packing is correct
void CAmalgamatedTexture::ValidateFramePacking( SequenceFrame *pBitmap, char *fileName )
{
if ( m_ePackingMode == PCKM_RGB_A )
{
for ( uint16 idx = 0; idx < pBitmap->m_mapSequences.Count(); ++idx )
{
Sequence *pSeq = pBitmap->m_mapSequences.Key( idx );
if ( pSeq->m_eMode != SQM_RGBA &&
pSeq->m_eMode != m_pCurSequence->m_eMode )
{
printf( "*** line error: 'rgb+a' packing cannot pack frame '%s' belonging to sequences %d and %d!\n",
fileName,
pSeq->m_nSequenceNumber,
m_pCurSequence->m_nSequenceNumber );
//printf( "*** line %d: 'rgb+a' packing cannot pack frame '%s' belonging to sequences %d and %d!\n",
// m_NumActualLinesRead,
// fileName,
// pSeq->m_nSequenceNumber,
// m_pCurSequence->m_nSequenceNumber );
exit( -1 );
}
}
}
}
void CAmalgamatedTexture::CreateFrame( float ftime, CUtlVector<char *> &frameNames )
{
SequenceEntry newSequenceEntry;
newSequenceEntry.m_fDisplayTime = ftime;
for ( int i = 0; i < frameNames.Count(); i++ )
{
LoadFrame( newSequenceEntry, frameNames[i], i );
}
m_pCurSequence->m_Frames.AddToTail( newSequenceEntry );
}
void CAmalgamatedTexture::LoadFrame( SequenceEntry &newSequenceEntry, char *fnamebuf, int frameNumber )
{
SequenceFrame *pBitmap;
// Store the frame in the image list, this is a string - bitmap mapping.
if ( ! ( m_ImageList.Defined( fnamebuf ) ) )
{
SequenceFrame *pNew_frm = new SequenceFrame;
pNew_frm->m_pImage = CreateFloatBitmap( fnamebuf );
pBitmap = pNew_frm;
m_ImageList[ fnamebuf ] = pNew_frm;
}
else
{
pBitmap = m_ImageList[ fnamebuf ];
}
newSequenceEntry.m_pSeqFrame[frameNumber] = pBitmap;
// Validate that frame packing is correct
ValidateFramePacking( pBitmap, fnamebuf );
pBitmap->m_mapSequences.Insert( m_pCurSequence, 1 );
if ( frameNumber == 0 )
{
for( int j = 1; j < MAX_IMAGES_PER_FRAME; j++ )
{
newSequenceEntry.m_pSeqFrame[j] = newSequenceEntry.m_pSeqFrame[0];
}
}
}
void CAmalgamatedTexture::DetermineBestPacking()
{
int nBestWidth = -1;
int nBestSize = (1 << 30 );
int nBestSquareness = ( 1 << 30 ); // how square the texture is
for( int nTryWidth = 2048 ; nTryWidth >= 64; nTryWidth >>= 1 )
{
bool bSuccess = PackImages( NULL, nTryWidth );
if ( bSuccess )
{
printf( "Packing option: %dx%d (%d pixels)\n", m_nWidth, m_nHeight, m_nWidth * m_nHeight );
bool bPreferThisPack = false;
int thisSize = m_nHeight * m_nWidth;
int thisSquareness = ( m_nWidth == m_nHeight ) ? 1 : ( m_nHeight / m_nWidth + m_nWidth / m_nHeight );
if ( thisSize < nBestSize )
{
bPreferThisPack = true;
}
else if ( thisSize == nBestSize && thisSquareness < nBestSquareness )
{
bPreferThisPack = true;
}
if ( bPreferThisPack )
{
nBestWidth = nTryWidth;
nBestSize = thisSize;
nBestSquareness = thisSquareness;
}
}
else
{
break;
}
}
if ( nBestWidth < 0 )
{
printf( "Packing error: failed to pack images!\n" );
exit(1);
}
m_nWidth = nBestWidth;
m_nHeight = nBestSize / nBestWidth;
printf( "Best option: %dx%d (%d pixels)%s\n", m_nWidth, m_nHeight, m_nWidth * m_nHeight, ( m_nWidth == m_nHeight ) ? " : square texture" : "" );
}
bool CAmalgamatedTexture::PackImages( char const *pFilename, int nWidth )
{
switch ( m_ePackingMode )
{
case PCKM_FLAT:
return PackImages_Flat( pFilename, nWidth );
case PCKM_RGB_A:
return PackImages_Rgb_A( pFilename, nWidth );
case PCKM_INVALID:
default:
return false;
}
}
bool CAmalgamatedTexture::PackImages_Flat( char const *pFilename, int nWidth )
{
// !! bug !! packing algorithm is dumb and no error checking is done!
FloatBitMap_t output( nWidth, 2048 );
int cur_line = 0;
int cur_column = 0;
int next_line = 0;
int max_column_written = 0;
for ( int i = 0; i < m_ImageList.GetNumStrings(); i++ )
{
SequenceFrame &frm = *(m_ImageList[i]);
if ( cur_column+frm.m_pImage->NumCols() > output.NumCols() )
{
// no room!
cur_column = 0;
cur_line = next_line;
next_line = cur_line;
}
// now, pack
if ( ( cur_column + frm.m_pImage->NumCols() > output.NumCols() ) ||
( cur_line + frm.m_pImage->NumRows() > output.NumRows() ) )
{
return false; // didn't fit! doh
}
frm.m_XCoord = cur_column;
frm.m_YCoord = cur_line;
if ( pFilename ) // don't actually pack the pixel if we're not keeping them
{
for ( int y = 0; y < frm.m_pImage->NumRows(); y++ )
for ( int x = 0; x < frm.m_pImage->NumCols(); x++ )
for ( int c = 0; c < 4; c++ )
{
output.Pixel( x+cur_column,y+cur_line, c ) = frm.m_pImage->Pixel(x, y, c);
}
}
next_line = max( next_line, cur_line+frm.m_pImage->NumRows() );
cur_column += frm.m_pImage->NumCols();
max_column_written = max( max_column_written, cur_column );
}
// now, truncate height
int h = 1;
for( h; h < next_line; h *= 2 )
;
// truncate width;
int w = 1;
for( 1; w < max_column_written; w *= 2 )
;
if ( pFilename )
{
FloatBitMap_t cropped_output( w, h );
for( int y = 0;y < cropped_output.NumRows(); y++ )
{
for( int x = 0; x < cropped_output.NumCols(); x++ )
{
for( int c = 0; c < 4; c++ )
{
cropped_output.Pixel( x,y,c ) = output.Pixel( x,y,c );
}
}
}
bool bWritten = cropped_output.WriteTGAFile( pFilename );
if ( !bWritten )
printf( "Error: failed to save TGA \"%s\"!\n", pFilename );
else
printf( "Ok: successfully saved TGA \"%s\"\n", pFilename );
}
// Store these for UV calculation later on
m_nHeight = h;
m_nWidth = w;
return true;
}
bool CAmalgamatedTexture::PackImages_Rgb_A( char const *pFilename, int nWidth )
{
// !! bug !! packing algorithm is dumb and no error checking is done!
FloatBitMap_t output( nWidth, 2048 );
int cur_line[2] = {0};
int cur_column[2] = {0};
int next_line[2] = {0};
int max_column_written[2] = {0};
bool bPackingRGBA = true;
for ( int i = 0; i < m_ImageList.GetNumStrings(); i++ )
{
SequenceFrame &frm = *( m_ImageList[i] );
int idxfrm;
int eMode = frm.m_mapSequences.Key( 0 )->m_eMode;
switch ( eMode )
{
case SQM_RGB:
idxfrm = 0;
bPackingRGBA = false;
break;
case SQM_ALPHA:
idxfrm = 1;
bPackingRGBA = false;
break;
case SQM_RGBA:
if ( !bPackingRGBA )
{
printf( "*** error when packing 'rgb+a', bad sequence %d encountered for frame '%s' after all rgba frames packed!\n",
frm.m_mapSequences.Key( 0 )->m_nSequenceNumber,
m_ImageList.String( i ) );
exit( -1 );
}
idxfrm = 0;
break;
default:
{
printf( "*** error when packing 'rgb+a', bad sequence %d encountered for frame '%s'!\n",
frm.m_mapSequences.Key( 0 )->m_nSequenceNumber,
m_ImageList.String( i ) );
exit( -1 );
}
}
if ( cur_column[idxfrm] + frm.m_pImage->NumCols() > output.NumCols() )
{
// no room!
cur_column[idxfrm] = 0;
cur_line[idxfrm] = next_line[idxfrm];
next_line[idxfrm] = cur_line[idxfrm];
}
// now, pack
if ( ( cur_column[idxfrm] + frm.m_pImage->NumCols() > output.NumCols() ) ||
( cur_line[idxfrm] + frm.m_pImage->NumRows() > output.NumRows() ) )
{
return false; // didn't fit! doh
}
frm.m_XCoord = cur_column[idxfrm];
frm.m_YCoord = cur_line[idxfrm];
if ( pFilename ) // don't actually pack the pixel if we're not keeping them
{
for ( int y = 0; y < frm.m_pImage->NumRows(); y++ )
{
for (int x = 0; x < frm.m_pImage->NumCols(); x++ )
{
for(int c = 0; c < 4; c ++ )
{
switch ( eMode )
{
case SQM_RGB:
if ( c < 3 )
goto setpx;
break;
case SQM_ALPHA:
if ( c == 3 )
goto setpx;
break;
case SQM_RGBA:
if ( c < 4 )
goto setpx;
break;
setpx:
output.Pixel( x + cur_column[idxfrm], y + cur_line[idxfrm], c ) = frm.m_pImage->Pixel(x, y, c);
}
}
}
}
}
next_line[idxfrm] = max( next_line[idxfrm], cur_line[idxfrm] + frm.m_pImage->NumRows() );
cur_column[idxfrm] += frm.m_pImage->NumCols();
max_column_written[idxfrm] = max( max_column_written[idxfrm], cur_column[idxfrm] );
if ( bPackingRGBA )
{
cur_line[1] = cur_line[0];
cur_column[1] = cur_column[0];
next_line[1] = next_line[0];
max_column_written[1] = max_column_written[0];
}
}
// now, truncate height
int h = 1;
for ( int idxfrm = 0; idxfrm < 2; ++idxfrm )
{
for ( h; h < next_line[idxfrm]; h *= 2 )
continue;
}
// truncate width;
int w = 1;
for ( int idxfrm = 0; idxfrm < 2; ++idxfrm )
{
for ( w; w < max_column_written[idxfrm]; w *= 2 )
continue;
}
if ( pFilename )
{
FloatBitMap_t cropped_output( w, h );
for( int y = 0; y < cropped_output.NumRows(); y++ )
{
for( int x = 0; x < cropped_output.NumCols(); x++ )
{
for( int c = 0; c < 4; c++ )
{
cropped_output.Pixel( x, y, c ) = output.Pixel( x, y, c );
}
}
}
bool bWritten = cropped_output.WriteTGAFile( pFilename );
if ( !bWritten )
{
printf( "Error: failed to save TGA \"%s\"!\n", pFilename );
}
else
{
printf( "Ok: successfully saved TGA \"%s\"\n", pFilename );
}
}
// Store these for UV calculation later on
m_nHeight = h;
m_nWidth = w;
return true;
}
void CAmalgamatedTexture::WriteFile()
{
if ( m_pShtFile == NULL )
{
printf( "Error: No output filename set!\n" );
return;
}
COutputFile Outfile( m_pShtFile );
if ( !Outfile.IsOk() )
{
printf( "Error: failed to write SHT \"%s\"!\n", m_pShtFile );
return;
}
Outfile.PutInt( 1 ); // version #
Outfile.PutInt( m_Sequences.Count() );
for ( int i = 0; i < m_Sequences.Count(); i++ )
{
Outfile.PutInt( m_Sequences[i]->m_nSequenceNumber );
Outfile.PutInt( m_Sequences[i]->m_Clamp );
Outfile.PutInt( m_Sequences[i]->m_Frames.Count() );
// write total sequence length
float fTotal = 0.0;
for ( int j = 0; j < m_Sequences[i]->m_Frames.Count(); j++ )
{
fTotal += m_Sequences[i]->m_Frames[j].m_fDisplayTime;
}
Outfile.PutFloat( fTotal );
for( int j = 0; j < m_Sequences[i]->m_Frames.Count(); j++ )
{
Outfile.PutFloat( m_Sequences[i]->m_Frames[j].m_fDisplayTime );
// output texture coordinates
for( int t = 0; t < MAX_IMAGES_PER_FRAME; t++ )
{
//xmin
Outfile.PutFloat( UCoord( m_Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_XCoord ) );
//ymin
Outfile.PutFloat( VCoord( m_Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_YCoord ) );
//xmax
Outfile.PutFloat(
UCoord( m_Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_XCoord +
m_Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_pImage->NumCols() - 1 ));
//ymax
Outfile.PutFloat(
VCoord( m_Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_YCoord +
m_Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_pImage->NumRows() - 1 ));
// printf( "T %d UV1:( %.2f, %.2f ) UV2:( %.2f, %.2f )\n", t,
// UCoord( Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_XCoord ),
// VCoord( Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_YCoord ),
// UCoord( Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_XCoord+Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_pImage->NumCols()-1 ),
// VCoord( Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_YCoord+Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_pImage->NumRows()-1 ));
}
}
}
printf( "Ok: successfully saved SHT \"%s\"\n", m_pShtFile );
}

View File

@@ -0,0 +1,112 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef AMALGAMATEDTEXTURE_H
#define AMALGAMATEDTEXTURE_H
#ifdef _WIN32
#pragma once
#endif
#include "amalg_texture_vars.h"
#include "bitmap/floatbitmap.h"
#include "tier1/utlmap.h"
#include "tier1/utlstringmap.h"
#include "tier2/tier2.h"
struct Sequence;
struct SequenceFrame
{
SequenceFrame() : m_mapSequences( DefLessFunc( Sequence * ) ) {}
FloatBitMap_t *m_pImage;
int m_XCoord, m_YCoord; // where it ended up packed
CUtlMap< Sequence *, int > m_mapSequences;
};
struct SequenceEntry
{
SequenceFrame *m_pSeqFrame[MAX_IMAGES_PER_FRAME];
float m_fDisplayTime;
};
struct Sequence
{
int m_nSequenceNumber;
bool m_Clamp; // as opposed to loop
int m_eMode;
CUtlVector<SequenceEntry> m_Frames;
Sequence( void )
{
m_Clamp = true;
m_eMode = SQM_RGBA;
}
};
// The texture itself.
class CAmalgamatedTexture
{
public:
CAmalgamatedTexture();
void Init( const char *pShtFileName = NULL );
void WriteFile();
void DetermineBestPacking();
bool PackImages( char const *pFilename, int nWidth );
int GetWidth() { return m_nWidth; }
void SetCurrentSequenceClamp( bool bState );
void SetPackingMode( int mode );
void CreateNewSequence( int sequenceNumber, int mode );
void ValidateSequenceType( int eMode, char *word );
void SetSequenceType( int eMode );
bool CurrentSequenceExists();
void CreateFrame( float ftime, CUtlVector<char *> &frameNames );
void LoadFrame( SequenceEntry &newSequenceEntry, char *fnamebuf, int frameNumber );
private:
int GetPackingMode();
int GetSequenceType();
void ValidateFramePacking( SequenceFrame *pBitmap, char *fileName );
bool PackImages_Flat( char const *pFilename, int nWidth );
bool PackImages_Rgb_A( char const *pFilename, int nWidth );
float UCoord( int u )
{
float uc = u + 0.5;
return uc / (float) m_nWidth;
}
float VCoord( int v )
{
float vc = v + 0.5;
return vc / (float) m_nHeight;
}
const char *m_pShtFile;
CUtlStringMap<SequenceFrame *> m_ImageList;
int m_ePackingMode;
CUtlVector<Sequence *> m_Sequences;
Sequence *m_pCurSequence;
int m_nWidth;
int m_nHeight;
};
#endif // AMALGAMATEDTEXTURE_H

View File

@@ -0,0 +1,279 @@
//===== Copyright <20> 2005-2006, Valve Corporation, All rights reserved. ======//
//
// Purpose: build a sheet data file and a large image out of multiple images
//
//===========================================================================//
#include "amalg_texture_parser.h"
#include "tier0/platform.h"
#include "tier0/progressbar.h"
#include "mathlib/mathlib.h"
#include "tier2/tier2.h"
#include "filesystem.h"
#include "tier1/utlstringmap.h"
#include "tier1/strtools.h"
#include "tier1/utlmap.h"
#include "tier2/fileutils.h"
#include "stdlib.h"
#include "materialobjects/dmeamalgtexture.h"
#include "tier1/utlbuffer.h"
#include "tier2/utlstreambuffer.h"
#include "tier0/dbg.h"
static void ApplyMacros( char * in_buf )
{
CUtlVector<char *> Words;
V_SplitString( in_buf, " ", Words);
if ( ( Words.Count() == 4 ) && (! stricmp( Words[0],"ga_frame") ) )
{
// ga_frame frm1 frm2 n -> frame frm1{r=a},frm1{g=a},frm1{b=a},frm2{a=a} n
sprintf( in_buf, "frame %s{r=0},%s{g=a},%s{b=0},%s{a=a} %s",
Words[1], Words[1], Words[1], Words[2], Words[3] );
}
Words.PurgeAndDeleteElements();
}
static char *MoveToStart( char *pLineBuffer )
{
// Kill newline '\n'
char *pChop = strchr( pLineBuffer, '\n' );
if ( pChop )
*pChop = 0;
// Kill '//' remove comment lines.
char *comment = Q_strstr( pLineBuffer, "//" );
if ( comment )
*comment = 0;
// Move to start of non-whitespace
char *in_str = pLineBuffer;
while( ( in_str[0]==' ' ) || ( in_str[0]=='\t') )
in_str++;
return in_str;
}
CAmalgamatedTextureParser::CAmalgamatedTextureParser()
{
m_pSourceFile = NULL;
m_pShtFile = NULL;
m_pTgaFile = NULL;
}
void CAmalgamatedTextureParser::Init( const char *pSourceFileName, const char *pTgaFileName, const char *pShtFileName )
{
m_pSourceFile = pSourceFileName;
m_pShtFile = pShtFileName;
m_pTgaFile = pTgaFileName;
}
int CAmalgamatedTextureParser::ParsePackingMode( char *word )
{
// Read in the packing mode requested.
int eRequestedMode = PCKM_INVALID;
if ( !stricmp( word, "flat" ) || !stricmp( word, "rgba" ) )
{
eRequestedMode = PCKM_FLAT;
}
else if ( !stricmp( word, "rgb+a" ) )
{
eRequestedMode = PCKM_RGB_A;
}
if ( eRequestedMode == PCKM_INVALID )
{
Warning( "*** line %d: invalid packmode specified, allowed values are 'rgba' or 'rgb+a'!\n", m_NumActualLinesRead );
}
return eRequestedMode;
}
int CAmalgamatedTextureParser::ParseSequenceType( char *word )
{
int eMode;
// Figure out the sequence type
char const *szSeqType = StringAfterPrefix( word, "sequence" );
if ( !stricmp( szSeqType, "" ) || !stricmp( szSeqType, "-rgba" ) )
{
eMode = SQM_RGBA;
}
else if ( !stricmp( szSeqType, "-rgb" ) )
{
eMode = SQM_RGB;
}
else if ( !stricmp( szSeqType, "-a" ) )
{
eMode = SQM_ALPHA;
}
else
{
Warning( "*** line %d: invalid sequence type '%s', allowed 'sequence-rgba' or 'sequence-rgb' or 'sequence-a'!\n", m_NumActualLinesRead, word ),
exit( -1 );
}
return eMode;
}
void CAmalgamatedTextureParser::ParseFrameImages( CUtlVector<char *> &words, CUtlVector<char *> &outImageNames )
{
for ( int i = 0; i < words.Count() - 2; i++ )
{
char *fnamebuf = words[i+1];
outImageNames.AddToTail( fnamebuf );
}
}
bool CAmalgamatedTextureParser::ReadFile( CDmeAmalgamatedTexture &amalgTex )
{
// FIXME handle file not found.
CRequiredInputTextFile f( m_pSourceFile );
char linebuffer[4096];
m_NumActualLinesRead = 0;
while ( f.ReadLine( linebuffer, sizeof(linebuffer) ) )
{
++m_NumActualLinesRead;
char *in_str = MoveToStart( linebuffer );
if ( in_str[0] == NULL )
continue;
strlwr( in_str ); // send string to lowercase.
ApplyMacros( in_str );
CUtlVector<char *> words;
V_SplitString( in_str, " ", words);
if ( ( words.Count() == 1) && (! stricmp( words[0],"loop" ) ) )
{
amalgTex.SetCurrentSequenceClamp( false );
}
else if ( ( words.Count() == 2 ) && (! stricmp( words[0], "packmode" ) ) )
{
// Read in the packing mode requested.
int eRequestedMode = ParsePackingMode( words[1] );
if ( eRequestedMode == PCKM_INVALID )
{
Msg( "Invalid packing mode." );
return false;
}
amalgTex.SetPackingMode( eRequestedMode );
}
else if ( ( words.Count() == 2) && StringHasPrefix( words[0], "sequence" ) )
{
int seq_no = atoi( words[1] );
if ( seq_no != amalgTex.GetSequenceCount() )
{
Warning( "Sequence number mismatch.\n" );
}
// Figure out the sequence type
int mode = ParseSequenceType( words[0] );
amalgTex.CreateNewSequence( mode );
}
else if ( ( words.Count() >= 3) && (! stricmp( words[0],"frame" ) ) )
{
if ( amalgTex.CurrentSequenceExists() )
{
float ftime = atof( words[ words.Count() - 1 ] );
CUtlVector<char *> imageNames;
ParseFrameImages( words, imageNames );
amalgTex.CreateFrame( imageNames, ftime );
}
}
else
{
Warning( "*** line %d: Bad command \"%s\"!\n", m_NumActualLinesRead, in_str ),
exit( -1 );
}
words.PurgeAndDeleteElements();
}
return true;
}
bool CAmalgamatedTextureParser::ReadFileUsingBuffer( CDmeAmalgamatedTexture &amalgTex )
{
CUtlBuffer buf( 0, 0, CUtlBuffer::READ_ONLY | CUtlBuffer::TEXT_BUFFER );
if ( !g_pFullFileSystem->ReadFile( m_pSourceFile, NULL, buf ) )
{
Warning( "CAmalgamatedTextureParser: Unable to open file '%s'\n", m_pSourceFile );
return false;
}
char linebuffer[4096];
m_NumActualLinesRead = 0;
while ( buf.IsValid() )
{
buf.GetLine( linebuffer, sizeof(linebuffer) );
++m_NumActualLinesRead;
char *in_str = MoveToStart( linebuffer );
if ( in_str[0] == NULL )
continue;
strlwr( in_str ); // send string to lowercase.
ApplyMacros( in_str );
CUtlVector<char *> words;
V_SplitString( in_str, " ", words);
if ( ( words.Count() == 1) && (! stricmp( words[0],"loop" ) ) )
{
amalgTex.SetCurrentSequenceClamp( false );
}
else if ( ( words.Count() == 2 ) && (! stricmp( words[0], "packmode" ) ) )
{
// Read in the packing mode requested.
int eRequestedMode = ParsePackingMode( words[1] );
amalgTex.SetPackingMode( eRequestedMode );
}
else if ( ( words.Count() == 2) && StringHasPrefix( words[0], "sequence" ) )
{
int seq_no = atoi( words[1] );
if ( seq_no != amalgTex.GetSequenceCount() )
{
Warning( "Sequence number mismatch.\n" );
}
// Figure out the sequence type
int mode = ParseSequenceType( words[0] );
amalgTex.CreateNewSequence( mode );
}
else if ( ( words.Count() >= 3) && (! stricmp( words[0],"frame" ) ) )
{
if ( amalgTex.CurrentSequenceExists() )
{
float ftime = atof( words[ words.Count() - 1 ] );
CUtlVector<char *> imageNames;
ParseFrameImages( words, imageNames );
amalgTex.CreateFrame( imageNames, ftime );
}
}
else
{
printf( "*** line %d: Bad command \"%s\"!\n", m_NumActualLinesRead, in_str ),
exit( -1 );
}
words.PurgeAndDeleteElements();
}
return true;
}

View File

@@ -0,0 +1,46 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef AMALGAMATEDTEXTUREPARSER_H
#define AMALGAMATEDTEXTUREPARSER_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utlvector.h"
class CAmalgamatedTexture;
class CDmeAmalgamatedTexture;
struct SequenceFrame;
// For parsing tool from the command line.
class CAmalgamatedTextureParser
{
public:
CAmalgamatedTextureParser();
void Init( const char *pSourceFileName, const char *pTgaFileName, const char *pShtFileName );
bool ReadFile( CDmeAmalgamatedTexture &amalgTex );
bool ReadFileUsingBuffer( CDmeAmalgamatedTexture &amalgTex );
void ParseFrameImages( CUtlVector<char *> &words, CUtlVector<char *> &outImageNames );
private:
int ParsePackingMode( char *word );
int ParseSequenceType( char *word );
void ValidateFramePacking( SequenceFrame *pBitmap, char *fileName );
const char *m_pSourceFile;
const char *m_pShtFile;
const char *m_pTgaFile;
int m_NumActualLinesRead;
};
#endif // AMALGAMATEDTEXTUREPARSER_H

View File

@@ -0,0 +1,35 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef AMALGAMATEDTEXTURE_VARS_H
#define AMALGAMATEDTEXTURE_VARS_H
#ifdef _WIN32
#pragma once
#endif
#include "filesystem.h"
#include "tier0/dbg.h"
#define MAX_IMAGES_PER_FRAME 4
enum PackingMode_t
{
PCKM_INVALID = 0,
PCKM_FLAT, // Default mode - every frame consumes entire RGBA space
PCKM_RGB_A, // Some sequences consume RGB space and some Alpha space
};
enum SeqMode_t
{
SQM_RGBA = 0, // Sequence occupies entire RGBA space
SQM_RGB = 1, // Sequence occupies only RGB space
SQM_ALPHA = 2 // Sequence occupies only Alpha space
};
#endif // AMALGAMATEDTEXTURE_VARS_H

View File

@@ -0,0 +1,99 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// Material editor
//=============================================================================
#include "mksutil.h"
#include "tier2/fileutils.h"
void CMksUtil::Init( const char *objectName )
{
m_SequenceCount = 0;
m_Name = objectName;
}
void CMksUtil::CreateNewSequenceEntry()
{
int index = m_MksEntries.AddToTail();
m_MksEntries[index].entryType = ENTRYTYPE_SEQUENCE;
m_MksEntries[index].sequenceNumber = m_SequenceCount;
m_SequenceCount++;
}
void CMksUtil::CreateNewFrameEntry( const char* pFrameName, float displayTime )
{
int index = m_MksEntries.AddToTail();
m_MksEntries[index].entryType = ENTRYTYPE_FRAME;
m_MksEntries[index].pFrameName = pFrameName;
m_MksEntries[index].displayTime = displayTime;
}
CUtlString CMksUtil::GetName()
{
return m_Name;
}
void CMksUtil::WriteFile()
{
if ( m_Name.IsEmpty() )
{
Msg( "Error: No mks output filename set!\n" );
return;
}
CUtlString mksFileName = m_Name;
mksFileName += ".mks";
char pMksFileFullPath[ MAX_PATH ];
if ( !GenerateFullPath( mksFileName, NULL, pMksFileFullPath, sizeof( pMksFileFullPath ) ) )
{
Warning( "CDataModel: Unable to generate full path for file %s\n", mksFileName );
return;
}
COutputTextFile Outfile( pMksFileFullPath );
if ( !Outfile.IsOk() )
{
Msg( "Error: failed to write MKS \"%s\"!\n", pMksFileFullPath );
return;
}
char buffer[33];
for ( int i = m_MksEntries.Head(); i < m_MksEntries.InvalidIndex(); i = m_MksEntries.Next( i ) )
{
if ( m_MksEntries[i].entryType == ENTRYTYPE_SEQUENCE )
{
Outfile.Write( "\n", sizeof( char ) );
Outfile.Write( "sequence ", sizeof( char ) * Q_strlen("sequence ") );
itoa( m_MksEntries[i].sequenceNumber, buffer, 10 );
Outfile.Write( buffer, sizeof( char ) * Q_strlen(buffer) );
}
else if ( m_MksEntries[i].entryType == ENTRYTYPE_FRAME )
{
Outfile.Write( "frame ", sizeof( char ) * Q_strlen("frame ") );
Outfile.Write( m_MksEntries[i].pFrameName, sizeof( char ) * Q_strlen(m_MksEntries[i].pFrameName) );
Outfile.Write( " ", sizeof( char ) );
sprintf( buffer, "%.1f", m_MksEntries[i].displayTime );
Outfile.Write( buffer, sizeof( char ) * Q_strlen(buffer) );
}
Outfile.Write( "\n", sizeof( char ) );
}
Msg( "Ok: successfully saved MKS \"%s\"\n", pMksFileFullPath );
}

View File

@@ -0,0 +1,61 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// Material editor
//=============================================================================
#ifndef MKSUTIL_H
#define MKSUTIL_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utllinkedlist.h"
#include "tier1/utlstring.h"
//-----------------------------------------------------------------------------
// The application object
//-----------------------------------------------------------------------------
class CMksUtil
{
public:
enum EntryType_t
{
ENTRYTYPE_SEQUENCE,
ENTRYTYPE_FRAME,
ENTRYTYPE_MAX
};
struct sMKSInfo
{
int entryType;
int sequenceNumber;
const char *pFrameName; // array?
float displayTime;
};
void Init( const char *objectName );
CUtlString GetName();
void CreateNewSequenceEntry();
void CreateNewFrameEntry( const char* pFrameName, float displayTime = 1.0f );
void WriteFile();
private:
CUtlLinkedList< sMKSInfo > m_MksEntries;
int m_SequenceCount;
CUtlString m_Name;
};
#endif // MKSUTIL_H

View File

@@ -0,0 +1,161 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// Material editor
//=============================================================================
#include "vstdlib/cvar.h"
#include "appframework/vguimatsysapp.h"
#include "nowindows.h"
#include "FileSystem.h"
#include "materialsystem/IMaterialSystem.h"
#include "vgui/IVGui.h"
#include "vgui/ISystem.h"
#include "vgui_controls/Panel.h"
#include "vgui/ISurface.h"
#include "vgui_controls/controls.h"
#include "vgui/IScheme.h"
#include "vgui/ILocalize.h"
#include "vgui/IPanel.h"
#include "tier0/dbg.h"
#include "vgui_controls/Frame.h"
#include "vgui_controls/AnimationController.h"
#include "tier0/icommandline.h"
#include "materialsystem/MaterialSystem_Config.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "filesystem_init.h"
#include "vstdlib/iprocessutils.h"
#include "matsys_controls/matsyscontrols.h"
#include "matsys_controls/mdlpicker.h"
#include "IStudioRender.h"
#include "datacache/idatacache.h"
#include "datacache/imdlcache.h"
#include "vphysics_interface.h"
#include "vgui_controls/frame.h"
#include "materialsystem/IMaterialSystemHardwareConfig.h"
#include "materialsystem/materialsystemutil.h"
#include "tier3/tier3.h"
#include "vgui_controls/consoledialog.h"
#include "icvar.h"
#include "vgui/keycode.h"
#include "vguimaterial.h"
#include "tier0/vprof.h"
#include "tier0/progressbar.h"
#include "amalg_texture_vars.h"
#include "amalg_texture.h"
#include "dmeamalgtexture.h"
#include "datamodel/dmelement.h"
#include "datamodel/dmelementfactoryhelper.h"
#include "tier2/fileutils.h"
#include "amalg_texture_parser.h"
#include "dmserializers/idmserializers.h"
//-----------------------------------------------------------------------------
// The application object
//-----------------------------------------------------------------------------
class CMksUtil
{
public:
enum
{
ENTRYTYPE_SEQUENCE,
ENTRYTYPE_FRAME,
ENTRYTYPE_MAX
};
struct sMKSInfo
{
int entryType;
int sequenceNumber;
const char *pFrameName; // array?
float displayTime;
};
void GenerateMKSEntries();
void GenerateMKSFile( const char *pMksFileName );
void CreateNewSequenceEntry();
void CreateNewFrameEntry( const char* pFrameName, float displayTime = 1.0f );
private:
CUtlLinkedList< sMKSInfo > m_MksEntries;
int m_SequenceCount;
};
void CMksUtil::CreateNewSequenceEntry()
{
int index = m_MksEntries.AddToTail();
m_MksEntries[index].entryType = ENTRYTYPE_SEQUENCE;
m_MksEntries[index].sequenceNumber = m_SequenceCount;
m_SequenceCount++;
}
void CMksUtil::CreateNewFrameEntry( const char* pFrameName, float displayTime )
{
int index = m_MksEntries.AddToTail();
m_MksEntries[index].entryType = ENTRYTYPE_FRAME;
m_MksEntries[index].pFrameName = pFrameName;
m_MksEntries[index].displayTime = displayTime;
}
void CMksUtil::GenerateMKSFile( const char *pMksFileName )
{
if ( pMksFileName == NULL )
{
Msg( "Error: No mks output filename set!\n" );
return;
}
char pMksFileFullPath[ MAX_PATH ];
if ( !GenerateFullPath( pMksFileName, NULL, pMksFileFullPath, sizeof( pMksFileFullPath ) ) )
{
Warning( "CDataModel: Unable to generate full path for file %s\n", pMksFileName );
return;
}
COutputTextFile Outfile( pMksFileFullPath );
if ( !Outfile.IsOk() )
{
Msg( "Error: failed to write MKS \"%s\"!\n", pMksFileFullPath );
return;
}
char buffer[33];
for ( int i = m_MksEntries.Head(); i < m_MksEntries.InvalidIndex(); i = m_MksEntries.Next( i ) )
{
if ( m_MksEntries[i].entryType == ENTRYTYPE_SEQUENCE )
{
Outfile.Write( "\n", sizeof( char ) );
Outfile.Write( "sequence ", sizeof( char ) * Q_strlen("sequence ") );
itoa( m_MksEntries[i].sequenceNumber, buffer, 10 );
Outfile.Write( buffer, sizeof( char ) * Q_strlen(buffer) );
}
else if ( m_MksEntries[i].entryType == ENTRYTYPE_FRAME )
{
Outfile.Write( "frame ", sizeof( char ) * Q_strlen("frame ") );
Outfile.Write( m_MksEntries[i].pFrameName, sizeof( char ) * Q_strlen(m_MksEntries[i].pFrameName) );
Outfile.Write( " ", sizeof( char ) );
sprintf( buffer, "%.1f", m_MksEntries[i].displayTime );
Outfile.Write( buffer, sizeof( char ) * Q_strlen(buffer) );
}
Outfile.Write( "\n", sizeof( char ) );
}
Msg( "Ok: successfully saved MKS \"%s\"\n", pMksFileFullPath );
}

View File

@@ -0,0 +1,491 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
// Material editor
//=============================================================================
#include "vstdlib/cvar.h"
#include "appframework/vguimatsysapp.h"
#include "soundsystem/isoundsystem.h"
#include "nowindows.h"
#include "FileSystem.h"
#include "vgui/IVGui.h"
#include "vgui/ISystem.h"
//#include "vgui/IScheme.h"
#include "vgui/ILocalize.h"
#include "vgui/ISurface.h"
#include "tier0/dbg.h"
#include "tier0/icommandline.h"
#include "materialsystem/MaterialSystem_Config.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "vstdlib/iprocessutils.h"
#include "matsys_controls/matsyscontrols.h"
#include "datacache/idatacache.h"
#include "vgui_controls/frame.h"
#include "materialsystem/IMaterialSystemHardwareConfig.h"
#include "materialsystem/materialsystemutil.h"
#include "vgui/keycode.h"
#include "tier0/vprof.h"
#include "inputsystem/iinputsystem.h"
#include "game_controls/igameuisystemmgr.h"
#include "console_logging.h"
#include "vscript/ivscript.h"
#include "materialsystem/imaterialproxyfactory.h"
#include "tier1/interface.h"
#include "materialsystem/IMaterialProxy.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
LINK_GAME_CONTROLS_LIB();
using namespace vgui;
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
const MaterialSystem_Config_t *g_pMaterialSystemConfig;
//-----------------------------------------------------------------------------
// A material proxy that resets the base texture to use the dynamic texture
//-----------------------------------------------------------------------------
class CPerftestGameControlsProxy : public IMaterialProxy
{
public:
CPerftestGameControlsProxy();
virtual ~CPerftestGameControlsProxy(){};
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pProxyData );
virtual void Release( void ) { delete this; }
virtual IMaterial *GetMaterial();
private:
IMaterialVar* m_BaseTextureVar;
};
CPerftestGameControlsProxy::CPerftestGameControlsProxy(): m_BaseTextureVar( NULL )
{
}
bool CPerftestGameControlsProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
bool bFoundVar;
m_BaseTextureVar = pMaterial->FindVar( "$basetexture", &bFoundVar, false );
return bFoundVar;
}
void CPerftestGameControlsProxy::OnBind( void *pProxyData )
{
const char *pBaseTextureName = ( const char * )pProxyData;
ITexture *pTexture = g_pMaterialSystem->FindTexture( pBaseTextureName, TEXTURE_GROUP_OTHER, true );
m_BaseTextureVar->SetTextureValue( pTexture );
}
IMaterial *CPerftestGameControlsProxy::GetMaterial()
{
return m_BaseTextureVar->GetOwningMaterial();
}
static CPerftestGameControlsProxy s_CPerftestGameControlsProxy;
//-----------------------------------------------------------------------------
// Factory to create dynamic material. ( Return in this case. )
//-----------------------------------------------------------------------------
class CPerftestMaterialProxyFactory : public IMaterialProxyFactory
{
public:
IMaterialProxy *CreateProxy( const char *proxyName );
void DeleteProxy( IMaterialProxy *pProxy );
CreateInterfaceFn GetFactory();
};
static CPerftestMaterialProxyFactory s_DynamicMaterialProxyFactory;
IMaterialProxy *CPerftestMaterialProxyFactory::CreateProxy( const char *proxyName )
{
if ( Q_strcmp( proxyName, "GameControlsProxy" ) == NULL )
{
return static_cast< IMaterialProxy * >( &s_CPerftestGameControlsProxy );
}
return NULL;
}
void CPerftestMaterialProxyFactory::DeleteProxy( IMaterialProxy *pProxy )
{
}
CreateInterfaceFn CPerftestMaterialProxyFactory::GetFactory()
{
return Sys_GetFactoryThis();
}
//-----------------------------------------------------------------------------
// The application object
//-----------------------------------------------------------------------------
class CVguiPerfTestApp : public CVguiMatSysApp
{
typedef CVguiMatSysApp BaseClass;
public:
// Methods of IApplication
virtual bool Create();
virtual bool PreInit();
virtual int Main();
virtual bool AppUsesReadPixels() { return true; }
private:
bool SetupSearchPaths();
virtual const char *GetAppName() { return "VguiPerfTest"; }
bool RunPerfTest( CMatRenderContextPtr &pRenderContext, const char *pMenuName );
void CVguiPerfTestApp::PlayMenuSound( const char *pSoundFileName );
};
DEFINE_WINDOWED_STEAM_APPLICATION_OBJECT( CVguiPerfTestApp );
//-----------------------------------------------------------------------------
// Create all singleton systems
//-----------------------------------------------------------------------------
bool CVguiPerfTestApp::Create()
{
if ( !BaseClass::Create() )
return false;
AppSystemInfo_t appSystems[] =
{
{ "vstdlib.dll", PROCESS_UTILS_INTERFACE_VERSION },
{ "vstdlib.dll", EVENTSYSTEM_INTERFACE_VERSION }, // input event support
// { "studiorender.dll", STUDIO_RENDER_INTERFACE_VERSION },
// { "vphysics.dll", VPHYSICS_INTERFACE_VERSION },
{ "datacache.dll", DATACACHE_INTERFACE_VERSION }, // needed for sound system.
// { "datacache.dll", MDLCACHE_INTERFACE_VERSION },
{ "vscript.dll", VSCRIPT_INTERFACE_VERSION }, // scripting support
{ "soundsystem.dll", SOUNDSYSTEM_INTERFACE_VERSION }, // sound support
{ "", "" } // Required to terminate the list
};
AddSystem( g_pGameUISystemMgr, GAMEUISYSTEMMGR_INTERFACE_VERSION );
return AddSystems( appSystems );
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CVguiPerfTestApp::PreInit( )
{
MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, false, false, false, false );
if ( !BaseClass::PreInit() )
return false;
// initialize interfaces
CreateInterfaceFn appFactory = GetFactory();
if (!vgui::VGui_InitMatSysInterfacesList( "VguiPerfTest", &appFactory, 1 ))
return false;
if ( !g_pFullFileSystem || !g_pMaterialSystem || !g_pVGui || !g_pVGuiSurface || !g_pMatSystemSurface || !g_pEventSystem )
{
Warning( "Perf Test App is missing a required interface!\n" );
return false;
}
// Add paths...
if ( !SetupSearchPaths() )
return false;
materials->SetMaterialProxyFactory( &s_DynamicMaterialProxyFactory );
return true;
}
//-----------------------------------------------------------------------------
// Sets up the game path
//-----------------------------------------------------------------------------
bool CVguiPerfTestApp::SetupSearchPaths()
{
if ( !BaseClass::SetupSearchPaths( NULL, false, true ) )
return false;
return true;
}
// Replace first underscore (if any) with \0 and return
// This handles special mods like tf_movies, l4d_movies, tf_comics
// As a result, such mods will use the gpu_level settings etc from the base mod
void StripModSuffix2( char *pModName )
{
int i = 0;
while ( pModName[i] != '\0' ) // Walk to the end of the string
{
if ( pModName[i] == '_') // If we hit an underscore
{
pModName[i] = '\0'; // Terminate the string here and bail out
return;
}
i++;
}
}
//-----------------------------------------------------------------------------
// main application
//-----------------------------------------------------------------------------
int CVguiPerfTestApp::Main()
{
CConsoleLoggingListener consoleLoggingListener;
LoggingSystem_PushLoggingState();
LoggingSystem_RegisterLoggingListener( &consoleLoggingListener );
LoggingSystem_SetChannelSpewLevelByTag( "Console", LS_MESSAGE );
LoggingSystem_SetChannelSpewLevelByTag( "Developer", LS_ERROR );
LoggingSystem_SetChannelSpewLevelByTag( "DeveloperVerbose", LS_ERROR );
CSimpleLoggingListener simpleLoggingListner( false );
LoggingSystem_RegisterLoggingListener( &simpleLoggingListner );
g_pMaterialSystem->ModInit();
if (!SetVideoMode())
return 0;
g_pDataCache->SetSize( 64 * 1024 * 1024 );
g_pMaterialSystemConfig = &g_pMaterialSystem->GetCurrentConfigForVideoCard();
// configuration settings
vgui::system()->SetUserConfigFile( "VguiPerfTest.vdf", "EXECUTABLE_PATH");
// If you load a vgui panel you must load up a scheme.
// load scheme
if (!vgui::scheme()->LoadSchemeFromFile( "resource/BoxRocket.res", "VguiPerfTest" ))
{
Assert( 0 );
}
// load the boxrocket localization file
g_pVGuiLocalize->AddFile( "resource/boxrocket_%language%.txt" );
// load the mod localization file
// Construct the mod name so we can use the mod-specific encrypted config files
char pModPath[MAX_PATH];
V_snprintf( pModPath, sizeof(pModPath), "" );
g_pFullFileSystem->GetSearchPath( "MOD", false, pModPath, sizeof( pModPath ) );
char pModName[32];
V_StripTrailingSlash( pModPath );
V_FileBase( pModPath, pModName, sizeof( pModName ) );
StripModSuffix2( pModName );
// Language file is a file of the form "resource/nimbus_%language%.txt"
CUtlString pModLanguageFile;
pModLanguageFile += "resource/";
pModLanguageFile += pModName;
pModLanguageFile += "_%language%.txt";
g_pVGuiLocalize->AddFile( pModLanguageFile.Get() );
// start vgui
g_pVGui->Start();
// add our main window
//vgui::PHandle hMainPanel;
// load the base localization file
g_pVGuiLocalize->AddFile( "Resource/valve_%language%.txt" );
g_pFullFileSystem->AddSearchPath( "platform", "PLATFORM" );
g_pVGuiLocalize->AddFile( "Resource/vgui_%language%.txt");
// run app frame loop
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
const char *pGuiFileName = CommandLine()->ParmValue( "-gui" );
bool bReload = true;
while ( bReload )
{
bReload = RunPerfTest( pRenderContext, pGuiFileName );
}
g_pMaterialSystem->ModShutdown();
LoggingSystem_PopLoggingState();
return 1;
}
//-----------------------------------------------------------------------------
// returns true if ui should reload
//-----------------------------------------------------------------------------
bool CVguiPerfTestApp::RunPerfTest( CMatRenderContextPtr &pRenderContext, const char *pMenuName )
{
g_pGameUISystemMgr->Shutdown();
g_pGameUISystemMgr->Init();
g_pMaterialSystem->BeginRenderTargetAllocation();
g_pGameUISystemMgr->InitRenderTargets();
g_pMaterialSystem->EndRenderTargetAllocation();
if ( !pMenuName )
{
pMenuName = "menu_1";
}
g_pGameUISystemMgr->LoadGameUIScreen( KeyValues::AutoDeleteInline(
new KeyValues( pMenuName ) ) );
g_VProfCurrentProfile.Reset();
g_VProfCurrentProfile.ResetPeaks();
g_VProfCurrentProfile.Start();
float m_flTotalTime = 0;
float flStartTime = Plat_FloatTime();
{
KeyValues *kvEvent = new KeyValues( "StartPlaying" );
kvEvent->SetFloat( "time", 0 );
g_pGameUISystemMgr->SendEventToAllScreens( kvEvent );
}
int frameCount = 0;
bool bReload = false;
bool bAbleToAdvance = true;
vgui::VPANEL root = g_pVGuiSurface->GetEmbeddedPanel();
g_pVGuiSurface->Invalidate( root );
while ( g_pVGui->IsRunning() )
{
AppPumpMessages();
g_pSoundSystem->Update( Plat_FloatTime() );
g_pMaterialSystem->BeginFrame( 0 );
pRenderContext->ClearColor4ub( 0, 0, 0, 255 );
//pRenderContext->ClearColor4ub( 76, 88, 68, 255 );
pRenderContext->ClearBuffers( true, true );
// Handle all input to game ui.
g_pGameUISystemMgr->RunFrame();
// Must call run frame for close button to work.
g_pVGui->RunFrame(); // need to load a default scheme for this to work.
//g_pVGuiSurface->PaintTraverseEx( root, true );
Rect_t viewport;
pRenderContext->GetViewport( viewport.x, viewport.y, viewport.width, viewport.height );
float flCurrentRenderTime = Plat_FloatTime() - flStartTime;
g_pGameUISystemMgr->Render( viewport, DmeTime_t( flCurrentRenderTime ) );
g_pMaterialSystem->EndFrame();
g_pMaterialSystem->SwapBuffers();
g_VProfCurrentProfile.MarkFrame();
frameCount++;
//if ( frameCount >= 5000 )
// break;
if ( g_pInputSystem->IsButtonDown( KEY_ESCAPE ) )
{
bReload = true;
break;
}
else if ( g_pInputSystem->IsButtonDown( KEY_PAD_PLUS ) )
{
m_flTotalTime = 0;
{
KeyValues *kvEvent = new KeyValues( "StartPlaying" );
kvEvent->SetFloat( "time", m_flTotalTime );
g_pGameUISystemMgr->SendEventToAllScreens( kvEvent );
}
}
else if ( g_pInputSystem->IsButtonDown( KEY_PAD_MINUS ) )
{
KeyValues *kvEvent = new KeyValues( "StopPlaying" );
g_pGameUISystemMgr->SendEventToAllScreens( kvEvent );
}
else if ( g_pInputSystem->IsButtonDown( KEY_PAD_DIVIDE ) )
{
KeyValues *kvEvent = new KeyValues( "ShowCursorCoords" );
g_pGameUISystemMgr->SendEventToAllScreens( kvEvent );
}
else if ( g_pInputSystem->IsButtonDown( KEY_PAD_9 ) )
{
KeyValues *kvEvent = new KeyValues( "ShowGraphicName" );
g_pGameUISystemMgr->SendEventToAllScreens( kvEvent );
}
else if ( g_pInputSystem->IsButtonDown( KEY_PAD_MULTIPLY ) )
{
if ( bAbleToAdvance )
{
KeyValues *kvEvent = new KeyValues( "AdvanceState" );
g_pGameUISystemMgr->SendEventToAllScreens( kvEvent );
}
bAbleToAdvance = false;
}
else if ( !g_pInputSystem->IsButtonDown( KEY_PAD_MULTIPLY ) )
{
bAbleToAdvance = true;
}
}
g_VProfCurrentProfile.Stop();
g_VProfCurrentProfile.OutputReport( VPRT_FULL & ~VPRT_HIERARCHY, NULL );
return bReload;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVguiPerfTestApp::PlayMenuSound( const char *pSoundFileName )
{
if ( pSoundFileName == NULL || pSoundFileName[ 0 ] == '\0' )
return;
if ( !Q_stristr( pSoundFileName, ".wav" ) )
return;
char filename[ 256 ];
sprintf( filename, "sound/%s", pSoundFileName );
CAudioSource *pAudioSource = g_pSoundSystem->FindOrAddSound( filename );
if ( pAudioSource == NULL )
return;
g_pSoundSystem->PlaySound( pAudioSource, 1.0f, NULL );
}

View File

@@ -0,0 +1,74 @@
//-----------------------------------------------------------------------------
// VGUI_PERFTEST.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Include "$SRCDIR\vpc_scripts\source_exe_win_win32_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE,$SRCDIR\vgui2\include,$SRCDIR\vgui2\controls,..\common"
}
$Linker
{
$AdditionalDependencies "$BASE comctl32.lib odbc32.lib odbccp32.lib Rpcrt4.lib Imm32.lib"
}
}
$Project "vguiPerfTest"
{
$Folder "Source Files"
{
$File "amalg_texture_parser.cpp"
$File "$SRCDIR\public\interpolatortypes.cpp"
$File "$SRCDIR\public\interpolatortypes.h"
$File "vgui_perftest.cpp"
$File "vguimaterial.cpp"
$File "$SRCDIR\public\vgui_controls\vgui_controls.cpp"
$File "$SRCDIR\public\studio.cpp"
$File "$SRCDIR\public\collisionutils.cpp"
$File "$SRCDIR\public\materialobjects\materialobjects.cpp"
$File "mksutil.cpp"
}
$Folder "Header Files"
{
$File "amalg_texture_parser.h"
$File "$SRCDIR\utils\common\cmdlib.h"
$File "$SRCDIR\common\console_logging.h"
$File "$SRCDIR\public\FileSystem.h"
$File "$SRCDIR\public\tier1\interface.h"
$File "vguimaterial.h"
$File "$SRCDIR\public\pixelwriter.h"
$File "mksutil.h"
$File "$SRCDIR\vgui2\game_controls\GameUISystem.h"
}
$Folder "Link Libraries"
{
$Lib "$LIBPUBLIC\bitmap"
$Lib "$LIBPUBLIC\datamodel"
$Lib "$LIBPUBLIC\dmserializers"
$Lib "$LIBPUBLIC\raytrace"
$Lib "$LIBPUBLIC\appframework"
$Lib "$LIBPUBLIC\dmxloader"
$Lib "$LIBPUBLIC\game_controls"
$Lib "$LIBPUBLIC\materialobjects"
$Lib "$LIBPUBLIC\mathlib"
$Lib "$LIBPUBLIC\matsys_controls"
$Lib "$LIBPUBLIC\resourcefile"
$Lib "$LIBPUBLIC\tier2"
$Lib "$LIBPUBLIC\tier3"
$Lib "$LIBPUBLIC\vtf"
$Lib "$LIBPUBLIC\vgui_controls"
$Lib "$LIBPUBLIC\vgui_surfacelib"
$Lib "$LIBPUBLIC\videocfg"
}
}

View File

@@ -0,0 +1,605 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
//=============================================================================
// tier 1
#include "tier1/strtools.h"
#include "utlvector.h"
#include "mathlib/vmatrix.h"
#include "FileSystem.h"
#include "bitmap/tgaloader.h"
#include "tier1/utlbuffer.h"
#include "tier1/utlstring.h"
#include "pixelwriter.h"
#include "vguimaterial.h"
#include "materialsystem/itexture.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/materialsystemutil.h"
#include "toolutils/enginetools_int.h"
#include "bitmap/imageformat.h"
#include "vtf/vtf.h"
#include "tier1/keyvalues.h"
#include "tier1/utllinkedlist.h"
#include "materialsystem/imesh.h"
#include <vstdlib/random.h>
#include "tier0/vprof.h"
#include "bitmap/psheet.h"
#include "materialsystem/imaterialvar.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <vfw.h>
#define MAX_LAYERS 10
enum
{
SUBLAYER_STATIC,
SUBLAYER_DYNAMIC,
SUBLAYER_FONT,
SUBLAYER_MAX,
};
//-----------------------------------------------------------------------------
// Class to render a zillion boxes with a tga material.
//-----------------------------------------------------------------------------
class CTGARenderer : public ITGARenderer
{
public:
void Init( int screenWidth, int screenHeight, int numTiles );
void Render();
void Shutdown();
private:
struct UIQuadInfo
{
public:
UIQuadInfo()
{
sublayer = -1;
sheetSequenceNumber = -1;
color.r = 255;
color.g = 255;
color.b = 255;
color.a = 255;
textureName = "";
}
UIQuadInfo( int inXPos, int inYPos, int inWidth, int inHeight, int inSublayer, int inSheetSeqNo )
{
Assign( inXPos, inYPos, inWidth, inHeight, inSublayer, inSheetSeqNo, color );
}
UIQuadInfo( int inXPos, int inYPos, int inWidth, int inHeight, int inSublayer, int inSheetSeqNo, color32 inColor )
{
Assign( inXPos, inYPos, inWidth, inHeight, inSublayer, inSheetSeqNo, inColor );
}
void Assign( int inXPos, int inYPos, int inWidth, int inHeight, int inSublayer, int inSheetSeqNo, color32 inColor )
{
x1Pos = inXPos;
y1Pos = inYPos;
width = inWidth;
height = inHeight;
x2Pos = x1Pos + width;
y2Pos = y1Pos + height;
Assert( inSheetSeqNo != -1 );
sublayer = inSublayer;
sheetSequenceNumber = inSheetSeqNo;
color = inColor;
}
int x1Pos;
int y1Pos;
int x2Pos;
int y2Pos;
int width;
int height;
CUtlString textureName; // name if the texture that is inside the sheet
int sheetSequenceNumber;
color32 color;
int sublayer;
};
struct SheetInfo
{
CUtlVector< CUtlString > m_SheetTexEntry;
};
SheetInfo m_sheetDict[SUBLAYER_MAX];
void AddSheetTextureEntry( int sublayer, const char *pTextureName );
int FindSheetTextureEntry( int sublayer, const char *pTextureName );
bool InitSheetTexture( int sublayer, const char *pBaseTextureName );
CSheet *CTGARenderer::LoadSheet( IMaterial *pMaterial );
CSheet *CTGARenderer::LoadSheet( char const *pszFname, ITexture *pTexture );
void GenerateUIMesh( CMatRenderContextPtr &pRenderContext, IMesh* pMesh, CUtlLinkedList< UIQuadInfo > &quads, CSheet *pSheet );
void InitTiles( int screenWidth, int screenHeight, int &xPos, int &yPos, int width, int height, int count, int layer, int sublayer, color32 color, const char *pTextureName = NULL );
void InitTiles( int screenWidth, int screenHeight, int &xPos, int &yPos, int width, int height, int count, int layer, int sublayer, const char *pTextureName );
void InitTiles( int screenWidth, int screenHeight, int &xPos, int &yPos, int width, int height, int count, int layer, int sublayer, int sheetSeqNo, color32 color );
void InitTiles( int screenWidth, int screenHeight, int &xPos, int &yPos, int width, int height, int count, int layer, int sublayer, int sheetSeqNo );
UIQuadInfo CreateQuad( int xPos, int yPos, int width, int height, int sublayer, const char *pTextureName = NULL );
UIQuadInfo CreateQuad( int xPos, int yPos, int width, int height, int sublayer, color32 color, const char *pTextureName = NULL );
void AddQuad( UIQuadInfo &quadInfo, int layer );
struct LayerTextureInfo
{
CMaterialReference m_SublayerMaterial;
CUtlReference< CSheet > m_Sheet;
};
LayerTextureInfo m_LayerTextureInfo[SUBLAYER_MAX];
struct LayerInfo
{
CUtlLinkedList< UIQuadInfo > *pQuads;
};
// For 3 draw call per layer test.
struct Layer
{
public:
// Layer 0 is static
// Layer 1 is dynamic
// Layer 2 is font
LayerInfo layerInfo[SUBLAYER_MAX];
};
// Test with 10 layers, 3 draw calls per layer.
CUtlVector< Layer > m_Layers;
bool m_bInitialized;
};
//-----------------------------------------------------------------------------
// Singleton
//-----------------------------------------------------------------------------
static CTGARenderer s_TGARenderer;
extern ITGARenderer *g_pTGARenderer = &s_TGARenderer;
// 3 drawcall one texture test.
void CTGARenderer::Init( int screenWidth, int screenHeight, int numTiles )
{
m_bInitialized = false;
// Build texture dictionary
AddSheetTextureEntry( SUBLAYER_STATIC, "pixel.tga" );
AddSheetTextureEntry( SUBLAYER_STATIC, "decalposter003a.tga" );
AddSheetTextureEntry( SUBLAYER_STATIC, "decalgraffiti037a.tga" );
AddSheetTextureEntry( SUBLAYER_STATIC, "Climb_node.tga" );
AddSheetTextureEntry( SUBLAYER_STATIC, "gibshooter.tga" );
AddSheetTextureEntry( SUBLAYER_STATIC, "ErrorIcon.tga" );;
AddSheetTextureEntry( SUBLAYER_DYNAMIC, "glassclock001a.tga" );
AddSheetTextureEntry( SUBLAYER_DYNAMIC, "decalgraffiti038a.tga" );
AddSheetTextureEntry( SUBLAYER_DYNAMIC, "Air_node_hint.tga" );
AddSheetTextureEntry( SUBLAYER_DYNAMIC, "info_lighting.tga" );
AddSheetTextureEntry( SUBLAYER_DYNAMIC, "SelfIllumIcon.tga" );
AddSheetTextureEntry( SUBLAYER_FONT, "glasswindow006a.tga" );
AddSheetTextureEntry( SUBLAYER_FONT, "decalgraffiti043a.tga" );
AddSheetTextureEntry( SUBLAYER_FONT, "Ground_node.tga" );
AddSheetTextureEntry( SUBLAYER_FONT, "info_target.tga" );
AddSheetTextureEntry( SUBLAYER_FONT, "translucenticon.tga" );
// Load the sheet textures.
bool bSuccess = InitSheetTexture( SUBLAYER_STATIC, "debug/sheettest/debug_meta1" );
if ( !bSuccess )
{
Warning( "CDataModel: Unable to load sheet for %s\n", "debug/sheettest/debug_meta1" );
return;
}
bSuccess = InitSheetTexture( SUBLAYER_DYNAMIC, "debug/sheettest/debug_meta2" );
if ( !bSuccess )
{
Warning( "CDataModel: Unable to load sheet for %s\n", "debug/sheettest/debug_meta2" );
return;
}
bSuccess = InitSheetTexture( SUBLAYER_FONT, "debug/sheettest/debug_meta3" );
if ( !bSuccess )
{
Warning( "CDataModel: Unable to load sheet for %s\n", "debug/sheettest/debug_meta3" );
return;
}
// Create an array of quads for each sublayer on each layer.
m_Layers.RemoveAll();
for ( int i = 0; i < MAX_LAYERS; ++i )
{
m_Layers.AddToTail();
for ( int j = 0; j < SUBLAYER_MAX; ++j )
{
m_Layers[i].layerInfo[j].pQuads = new CUtlLinkedList< UIQuadInfo >;
}
}
UIQuadInfo testQuad;
testQuad = CreateQuad( 0, 0, 64, 64, SUBLAYER_STATIC, "gibshooter.tga" );
AddQuad( testQuad, 0 );
testQuad = CreateQuad( 0, 128, 128, 128, SUBLAYER_DYNAMIC, "Air_node_hint.tga" );
AddQuad( testQuad, 0 );
m_bInitialized = true;
}
bool CTGARenderer::InitSheetTexture( int sublayer, const char *pBaseTextureName )
{
CUtlString materialName;
switch (sublayer)
{
case SUBLAYER_STATIC:
materialName = "statictx";
break;
case SUBLAYER_DYNAMIC:
materialName = "dynamictx";
break;
case SUBLAYER_FONT:
materialName = "fonttx";
break;
default:
Warning( "CTGARenderer: Invalid sublayer for %s\n", pBaseTextureName );
Assert(0);
break;
};
KeyValues *pVMTKeyValues = new KeyValues( "GameControls" );
pVMTKeyValues->SetString( "$basetexture", pBaseTextureName );
m_LayerTextureInfo[sublayer].m_SublayerMaterial.Init( materialName, TEXTURE_GROUP_OTHER, pVMTKeyValues );
m_LayerTextureInfo[sublayer].m_SublayerMaterial->Refresh();
CSheet *pSheet = LoadSheet( m_LayerTextureInfo[sublayer].m_SublayerMaterial );
if ( pSheet == NULL )
{
Warning( "CTGARenderer: Unable to load sheet for %s %s\n", materialName.Get(), pBaseTextureName );
return false;
}
else
{
m_LayerTextureInfo[sublayer].m_Sheet.Set( pSheet );
return true;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CTGARenderer::InitTiles( int screenWidth, int screenHeight, int &xPos, int &yPos, int width, int height, int count, int layer, int sublayer, int sheetSeqNo, color32 color )
{
CUtlLinkedList< UIQuadInfo > *pQuads = m_Layers[layer].layerInfo[sublayer].pQuads;
for ( int i = 0; i < count; ++i )
{
UIQuadInfo quadInfo( xPos, yPos, width, height, sublayer, sheetSeqNo, color );
pQuads->AddToTail( quadInfo );
xPos += width;
if ( xPos >= screenWidth )
{
xPos = 0;
yPos += height;
}
if ( yPos >= screenHeight )
{
// just wrap.
yPos = 0;
}
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CTGARenderer::InitTiles( int screenWidth, int screenHeight, int &xPos, int &yPos, int width, int height, int count, int layer, int sublayer, int sheetSeqNo )
{
for ( int i = 0; i < count; ++i )
{
UIQuadInfo quadInfo( xPos, yPos, width, height, sublayer, sheetSeqNo );
AddQuad( quadInfo, layer );
xPos += width;
if ( xPos >= screenWidth )
{
xPos = 0;
yPos += height;
}
if ( yPos >= screenHeight )
{
// just wrap.
yPos = 0;
}
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CTGARenderer::InitTiles( int screenWidth, int screenHeight, int &xPos, int &yPos, int width, int height, int count,
int layer, int sublayer, color32 color, const char *pTextureName )
{
int sheetSeqNo = FindSheetTextureEntry( sublayer, pTextureName );
Assert( sheetSeqNo != -1 );
InitTiles( screenWidth, screenHeight, xPos, yPos, width, height, count, layer, sublayer, sheetSeqNo, color );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CTGARenderer::InitTiles( int screenWidth, int screenHeight, int &xPos, int &yPos, int width, int height, int count,
int layer, int sublayer, const char *pTextureName )
{
int sheetSeqNo = FindSheetTextureEntry( sublayer, pTextureName );
InitTiles( screenWidth, screenHeight, xPos, yPos, width, height, count, layer, sublayer, sheetSeqNo );
}
//-----------------------------------------------------------------------------
// Create a quad on a sublayer
// Texture name is optional.
//-----------------------------------------------------------------------------
CTGARenderer::UIQuadInfo CTGARenderer::CreateQuad( int xPos, int yPos, int width, int height, int sublayer, const char *pTextureName )
{
int sheetSeqNo = FindSheetTextureEntry( sublayer, pTextureName );
UIQuadInfo quadInfo( xPos, yPos, width, height, sublayer, sheetSeqNo );
return quadInfo;
}
//-----------------------------------------------------------------------------
// Create a quad on a sublayer
// Texture name is optional.
//-----------------------------------------------------------------------------
CTGARenderer::UIQuadInfo CTGARenderer::CreateQuad( int xPos, int yPos, int width, int height, int sublayer, color32 color, const char *pTextureName )
{
int sheetSeqNo = FindSheetTextureEntry( sublayer, pTextureName );
UIQuadInfo quadInfo( xPos, yPos, width, height, sublayer, sheetSeqNo, color );
return quadInfo;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CTGARenderer::AddQuad( UIQuadInfo &quadInfo, int layer )
{
CUtlLinkedList< UIQuadInfo > *pQuads = m_Layers[layer].layerInfo[quadInfo.sublayer].pQuads;
pQuads->AddToTail( quadInfo );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CTGARenderer::AddSheetTextureEntry( int sublayer, const char *pTextureName )
{
m_sheetDict[sublayer].m_SheetTexEntry.AddToTail( pTextureName );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int CTGARenderer::FindSheetTextureEntry( int sublayer, const char *pTextureName )
{
if ( pTextureName == NULL )
return 0;
for ( int i = 0; i < m_sheetDict[sublayer].m_SheetTexEntry.Count(); ++i )
{
if ( !Q_strcmp( m_sheetDict[sublayer].m_SheetTexEntry[i], pTextureName ) )
return i;
}
Assert(0);
return -1;
}
#include "vgui/ISurface.h"
#include "vguimatsurface/imatsystemsurface.h"
//-----------------------------------------------------------------------------
// 3 draw calls per layer.
//-----------------------------------------------------------------------------
void CTGARenderer::Render()
{
VPROF_BUDGET( "Render", "Render" );
if ( !m_bInitialized )
{
Warning( "CTGARenderer: Unable to render.\n" );
return;
}
int x, y, width, height;
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
pRenderContext->ClearColor4ub( 76, 88, 68, 255 );
pRenderContext->ClearBuffers( true, true );
pRenderContext->GetViewport( x, y, width, height);
float flPixelOffsetX = 0.5f;
float flPixelOffsetY = 0.5f;
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
pRenderContext->Scale( 1, -1, 1 );
pRenderContext->Ortho( flPixelOffsetX, flPixelOffsetY, width + flPixelOffsetX, height + flPixelOffsetY, -1.0f, 1.0f );
// make sure there is no translation and rotation laying around
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
// each sublayer should correspond to one meta texture binding.
for ( int i = 0; i < MAX_LAYERS; ++i )
{
for ( int j = 0; j < SUBLAYER_MAX; ++j )
{
if ( m_Layers[i].layerInfo[j].pQuads->Count() == 0 )
{
continue;
}
pRenderContext->Bind( m_LayerTextureInfo[j].m_SublayerMaterial, NULL );
IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
GenerateUIMesh( pRenderContext, pMesh, *(m_Layers[i].layerInfo[j].pQuads), m_LayerTextureInfo[j].m_Sheet );
pMesh->Draw();
}
}
// Restore the matrices
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->PopMatrix();
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PopMatrix();
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PopMatrix();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CTGARenderer::Shutdown()
{
int count = 0;
for ( int i = 0; i < MAX_LAYERS; ++i )
{
for ( int j = 0; j < SUBLAYER_MAX; j++ )
{
count += m_Layers[i].layerInfo[j].pQuads->Count();
}
}
Warning( "Total generated quads = %d\n", count );
m_Layers.RemoveAll();
}
//--------------------------------------------------------------------------------
// UI sheets
//--------------------------------------------------------------------------------
CSheet *CTGARenderer::LoadSheet( char const *pszFname, ITexture *pTexture )
{
CSheet *pNewSheet = NULL;
// get compact sheet representation held by texture
size_t numBytes;
void const *pSheet = pTexture->GetResourceData( VTF_RSRC_SHEET, &numBytes );
if ( pSheet )
{
// expand compact sheet into fatter runtime form
CUtlBuffer bufLoad( pSheet, numBytes, CUtlBuffer::READ_ONLY );
pNewSheet = new CSheet( bufLoad );
}
//m_SheetList[ pszFname ] = pNewSheet;
return pNewSheet;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CSheet *CTGARenderer::LoadSheet( IMaterial *pMaterial )
{
if ( !pMaterial )
return NULL;
bool bFoundVar = false;
IMaterialVar *pVar = pMaterial->FindVar( "$basetexture", &bFoundVar, true );
if ( bFoundVar && pVar && pVar->IsDefined() )
{
ITexture *pTex = pVar->GetTextureValue();
if ( pTex && !pTex->IsError() )
return LoadSheet( pTex->GetName(), pTex );
}
return NULL;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CTGARenderer::GenerateUIMesh( CMatRenderContextPtr &pRenderContext, IMesh* pMesh, CUtlLinkedList< UIQuadInfo > &quads, CSheet *pSheet )
{
VPROF_BUDGET( "GenerateUIMesh", "GenerateUIMesh" );
if ( quads.Count() == 0 )
return;
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_QUADS, quads.Count() );
int x, y, width, height;
pRenderContext->GetViewport( x, y, width, height);
{
VPROF_BUDGET( "meshBuilder", "meshBuilder" );
for( int i = quads.Head(); i != quads.InvalidIndex(); i = quads.Next( i ) )
{
Assert( pSheet );
Assert( pSheet->m_SheetInfo[quads[i].sheetSequenceNumber].m_pSamples );
SheetSequenceSample_t *pSample = pSheet->m_SheetInfo[quads[i].sheetSequenceNumber].m_pSamples;
Assert( pSample );
const SequenceSampleTextureCoords_t *pSample0 = &(pSample->m_TextureCoordData[0]);
Assert( pSample0 );
color32 c = quads[i].color;
// Top left
meshBuilder.Position3f( quads[i].x1Pos, quads[i].y1Pos, 0.0f );
meshBuilder.Color4ub( c.r, c.g, c.b, c.a );
meshBuilder.TexCoord3f( 0, pSample0->m_fLeft_U0, pSample0->m_fTop_V0, 0 );
meshBuilder.AdvanceVertex();
// Top right
meshBuilder.Position3f( quads[i].x2Pos, quads[i].y1Pos, 0.0f );
meshBuilder.Color4ub( c.r, c.g, c.b, c.a );
meshBuilder.TexCoord3f( 0, pSample0->m_fRight_U0, pSample0->m_fTop_V0, 0 );
meshBuilder.AdvanceVertex();
// Bottom right
meshBuilder.Position3f( quads[i].x2Pos, quads[i].y2Pos, 0.0f );
meshBuilder.Color4ub( c.r, c.g, c.b, c.a );
meshBuilder.TexCoord3f( 0, pSample0->m_fRight_U0, pSample0->m_fBottom_V0, 0 );
meshBuilder.AdvanceVertex();
// Bottom left
meshBuilder.Position3f( quads[i].x1Pos, quads[i].y2Pos, 0.0f );
meshBuilder.Color4ub( c.r, c.g, c.b, c.a );
meshBuilder.TexCoord3f( 0, pSample0->m_fLeft_U0, pSample0->m_fBottom_V0, 0 );
meshBuilder.AdvanceVertex();
}
}
meshBuilder.End();
}

View File

@@ -0,0 +1,24 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef VGUIMATERIALS_H
#define VGUIMATERIALS_H
#ifdef _WIN32
#pragma once
#endif
class ITGARenderer
{
public:
virtual void Init( int screenWidth, int screenHeight, int numTiles ) = 0;
virtual void Render() = 0;
virtual void Shutdown() = 0;
};
extern ITGARenderer *g_pTGARenderer;
#endif // VGUIMATERIALS_H