summaryrefslogtreecommitdiff
path: root/utils/mksheet
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/mksheet
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'utils/mksheet')
-rw-r--r--utils/mksheet/alpha1.tgabin0 -> 262188 bytes
-rw-r--r--utils/mksheet/alpha2.tgabin0 -> 262188 bytes
-rw-r--r--utils/mksheet/mksheet.cpp691
-rw-r--r--utils/mksheet/mksheet.vpc36
-rw-r--r--utils/mksheet/sheet0.txt32
-rw-r--r--utils/mksheet/testimages/rockettrail000.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail001.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail002.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail003.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail004.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail005.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail006.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail007.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail008.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail009.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail010.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail011.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail012.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail013.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail014.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail015.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail016.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail017.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail018.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail019.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail020.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail021.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail022.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail023.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail024.tgabin0 -> 65580 bytes
-rw-r--r--utils/mksheet/testimages/rockettrail025.tgabin0 -> 65580 bytes
31 files changed, 759 insertions, 0 deletions
diff --git a/utils/mksheet/alpha1.tga b/utils/mksheet/alpha1.tga
new file mode 100644
index 0000000..0d390ae
--- /dev/null
+++ b/utils/mksheet/alpha1.tga
Binary files differ
diff --git a/utils/mksheet/alpha2.tga b/utils/mksheet/alpha2.tga
new file mode 100644
index 0000000..5b23212
--- /dev/null
+++ b/utils/mksheet/alpha2.tga
Binary files differ
diff --git a/utils/mksheet/mksheet.cpp b/utils/mksheet/mksheet.cpp
new file mode 100644
index 0000000..3345054
--- /dev/null
+++ b/utils/mksheet/mksheet.cpp
@@ -0,0 +1,691 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: build a sheet data file and a large image out of multiple images
+//
+//===========================================================================//
+
+#include "tier0/platform.h"
+#include "tier0/progressbar.h"
+#include "bitmap/float_bm.h"
+#include "mathlib/mathlib.h"
+#include "tier2/tier2.h"
+#include "tier0/memdbgon.h"
+#include "filesystem.h"
+#include "tier1/utlstringmap.h"
+#include "tier1/strtools.h"
+#include "tier1/utlmap.h"
+#include "bitmap/float_bm.h"
+#include "tier2/fileutils.h"
+#include "stdlib.h"
+
+#include "tier0/dbg.h"
+
+#define MAX_IMAGES_PER_FRAME 4
+
+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;
+};
+
+
+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
+};
+
+static CUtlStringMap<SequenceFrame *> ImageList;
+static PackingMode_t s_ePackingMode = PCKM_FLAT;
+
+struct SequenceEntry
+{
+ SequenceFrame *m_pSeqFrame[MAX_IMAGES_PER_FRAME];
+ float m_fDisplayTime;
+};
+
+struct Sequence
+{
+ 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
+ };
+
+ int m_nSequenceNumber;
+ bool m_Clamp; // as opposed to loop
+ SeqMode_t m_eMode;
+ CUtlVector<SequenceEntry> m_Frames;
+
+ Sequence( void )
+ {
+ m_Clamp = true;
+ m_eMode = SQM_RGBA;
+ }
+
+};
+
+
+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 FloatBitMap_t *CreateFBM( const char * fname )
+{
+ if ( strchr( fname, ',' ) )
+ {
+ // parse extended specifications
+ CUtlVector<char *> Images;
+ V_SplitString( fname, ",", Images);
+ FloatBitMap_t *pBM = 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 NewBM( fnamebuf );
+ if ( ! pBM )
+ {
+ // first image sets size
+ pBM = new FloatBitMap_t( &NewBM );
+ }
+ // now, process operation specifiers of the form "{chan=chan}" or "{chan=0}"
+ if ( pBrace )
+ {
+ if ( pBrace[1] == '=' )
+ {
+ int nDstChan = GetChannelIndexFromChar( pBrace[0] );
+ if ( nDstChan != -1 )
+ {
+ if ( pBrace[2] == '0' )
+ {
+ // zero the channel
+ for(int y = 0; y < NewBM.Height; y++ )
+ for(int x=0; x < NewBM.Width; x++ )
+ {
+ pBM->Pixel( x, y, nDstChan ) = 0;
+ }
+ }
+ else
+ {
+ int nSrcChan = GetChannelIndexFromChar( pBrace[2] );
+ if ( nSrcChan != -1 )
+ {
+ // perform the channel copy
+ for(int y = 0; y < NewBM.Height; y++ )
+ for(int x=0; x < NewBM.Width; x++ )
+ {
+ pBM->Pixel( x, y, nDstChan ) = NewBM.Pixel( x, y, nSrcChan );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return pBM;
+ }
+ else
+ return new FloatBitMap_t( fname );
+}
+
+static CUtlVector< Sequence *> Sequences;
+
+static Sequence *pCurSequence=NULL;
+
+static int s_nWidth;
+static int s_nHeight;
+
+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 void ReadTextControlFile( char const *fname )
+{
+ CRequiredInputTextFile f( fname );
+ char linebuffer[4096];
+ bool numActualLinesRead = 0;
+ while ( f.ReadLine( linebuffer, sizeof(linebuffer) ) )
+ {
+ ++ numActualLinesRead;
+
+ // kill newline
+ char *pChop=strchr( linebuffer, '\n' );
+ if ( pChop )
+ *pChop = 0;
+
+ char *comment=Q_strstr( linebuffer, "//" );
+ if ( comment )
+ *comment = 0;
+ char *in_str=linebuffer;
+ while( ( in_str[0]==' ' ) || ( in_str[0]=='\t') )
+ in_str++;
+
+ if (in_str[0])
+ {
+ strlwr( in_str );
+ ApplyMacros( in_str );
+ CUtlVector<char *> Words;
+ V_SplitString( in_str, " ", Words);
+ if ( ( Words.Count() == 1) && (! stricmp( Words[0],"loop" ) ) )
+ {
+ if ( pCurSequence )
+ pCurSequence->m_Clamp = false;
+ }
+ else if ( ( Words.Count() == 2 ) && (! stricmp( Words[0], "packmode" ) ) )
+ {
+ PackingMode_t eRequestedMode = PCKM_INVALID;
+ if ( !stricmp( Words[1], "flat" ) || !stricmp( Words[1], "rgba" ) )
+ eRequestedMode = PCKM_FLAT;
+ else if ( !stricmp( Words[1], "rgb+a" ) )
+ eRequestedMode = PCKM_RGB_A;
+
+ if ( eRequestedMode == PCKM_INVALID )
+ printf( "*** line %d: invalid packmode specified, allowed values are 'rgba' or 'rgb+a'!\n", numActualLinesRead ),
+ exit( -1 );
+ else if ( !Sequences.Count() )
+ s_ePackingMode = eRequestedMode;
+ else if ( s_ePackingMode != eRequestedMode )
+ {
+ // Allow special changes:
+ // flat -> rgb+a
+ if ( s_ePackingMode == PCKM_FLAT && eRequestedMode == PCKM_RGB_A )
+ s_ePackingMode = eRequestedMode;
+ // everything else
+ else
+ printf( "*** line %d: incompatible packmode change when %d sequences already defined!\n", numActualLinesRead, Sequences.Count() ),
+ exit( -1 );
+ }
+ }
+ else if ( ( Words.Count() == 2) && StringHasPrefix( Words[0], "sequence" ) )
+ {
+ int seq_no = atoi( Words[1] );
+ pCurSequence = new Sequence;
+ pCurSequence->m_nSequenceNumber = seq_no;
+
+ // Figure out the sequence type
+ char const *szSeqType = StringAfterPrefix( Words[0], "sequence" );
+ if ( !stricmp( szSeqType, "" ) || !stricmp( szSeqType, "-rgba" ) )
+ pCurSequence->m_eMode = Sequence::SQM_RGBA;
+ else if ( !stricmp( szSeqType, "-rgb" ) )
+ pCurSequence->m_eMode = Sequence::SQM_RGB;
+ else if ( !stricmp( szSeqType, "-a" ) )
+ pCurSequence->m_eMode = Sequence::SQM_ALPHA;
+ else
+ printf( "*** line %d: invalid sequence type '%s', allowed 'sequence-rgba' or 'sequence-rgb' or 'sequence-a'!\n", numActualLinesRead, Words[0] ),
+ exit( -1 );
+
+ // Validate sequence type
+ switch ( s_ePackingMode )
+ {
+ case PCKM_FLAT:
+ switch ( pCurSequence->m_eMode )
+ {
+ case Sequence::SQM_RGBA: break;
+ default:
+ printf( "*** line %d: invalid sequence type '%s', packing 'flat' allows only 'sequence-rgba'!\n", numActualLinesRead, Words[0] ),
+ exit( -1 );
+ }
+ break;
+ case PCKM_RGB_A:
+ switch ( pCurSequence->m_eMode )
+ {
+ case Sequence::SQM_RGB:
+ case Sequence::SQM_ALPHA: break;
+ default:
+ printf( "*** line %d: invalid sequence type '%s', packing 'rgb+a' allows only 'sequence-rgb' or 'sequence-a'!\n", numActualLinesRead, Words[0] ),
+ exit( -1 );
+ }
+ break;
+ }
+
+ Sequences.AddToTail( pCurSequence );
+ }
+ else if ( ( Words.Count() >= 3) && (! stricmp( Words[0],"frame" ) ) )
+ {
+ if ( pCurSequence )
+ {
+ float ftime = atof( Words[ Words.Count() - 1 ] );
+ SequenceEntry new_entry;
+ new_entry.m_fDisplayTime = ftime;
+ for(int i=0;i < Words.Count()-2; i++)
+ {
+ SequenceFrame *pBM;
+ char * fnamebuf = Words[i+1];
+ if ( ! ( ImageList.Defined( fnamebuf ) ) )
+ {
+ SequenceFrame *pNew_frm = new SequenceFrame;
+ pNew_frm->m_pImage = CreateFBM( fnamebuf );
+ pBM=pNew_frm;
+ ImageList[ fnamebuf ] = pNew_frm;
+ }
+ else
+ pBM = ImageList[ fnamebuf ];
+
+ new_entry.m_pSeqFrame[i] = pBM;
+
+ // Validate that frame packing is correct
+ if ( s_ePackingMode == PCKM_RGB_A )
+ {
+ for ( uint16 idx = 0; idx < pBM->m_mapSequences.Count(); ++ idx )
+ {
+ Sequence *pSeq = pBM->m_mapSequences.Key( idx );
+ if ( pSeq->m_eMode != Sequence::SQM_RGBA &&
+ pSeq->m_eMode != pCurSequence->m_eMode )
+ {
+ printf( "*** line %d: 'rgb+a' packing cannot pack frame '%s' belonging to sequences %d and %d!\n", numActualLinesRead,
+ fnamebuf,
+ pSeq->m_nSequenceNumber, pCurSequence->m_nSequenceNumber ),
+ exit( -1 );
+ }
+ }
+ }
+
+ pBM->m_mapSequences.Insert( pCurSequence, 1 );
+
+ if (i == 0 )
+ for( int j=1; j<MAX_IMAGES_PER_FRAME; j++ )
+ new_entry.m_pSeqFrame[j]=new_entry.m_pSeqFrame[0];
+ }
+ pCurSequence->m_Frames.AddToTail( new_entry );
+ }
+ }
+ else
+ {
+ printf("*** line %d: Bad command \"%s\"!\n", numActualLinesRead, in_str ),
+ exit( -1 );
+ }
+ Words.PurgeAndDeleteElements();
+ }
+ }
+}
+
+
+inline float UCoord( int u )
+{
+ float uc=u+0.5;
+ return uc/(float) s_nWidth;
+}
+inline float VCoord( int v )
+{
+ float vc=v+0.5;
+ return vc/(float) s_nHeight;
+}
+
+bool PackImages_Flat( char const *pFname, 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 < ImageList.GetNumStrings(); i++)
+ {
+ SequenceFrame &frm=*(ImageList[i]);
+ if ( cur_column+frm.m_pImage->Width > output.Width )
+ {
+ // no room!
+ cur_column = 0;
+ cur_line = next_line;
+ next_line = cur_line;
+ }
+ // now, pack
+ if ( ( cur_column+frm.m_pImage->Width > output.Width ) ||
+ ( cur_line+frm.m_pImage->Height > output.Height ) )
+ {
+ return false; // didn't fit! doh
+ }
+
+ frm.m_XCoord=cur_column;
+ frm.m_YCoord=cur_line;
+
+ if ( pFname ) // don't actually pack the pixel if we're not keeping them
+ {
+ for(int y=0;y<frm.m_pImage->Height; y++)
+ for(int x=0;x<frm.m_pImage->Width; 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->Height );
+ cur_column += frm.m_pImage->Width;
+ 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 ( pFname )
+ {
+ FloatBitMap_t cropped_output( w, h);
+ for(int y=0;y<cropped_output.Height; y++)
+ for(int x=0;x<cropped_output.Width; x++)
+ for(int c=0;c<4;c++)
+ cropped_output.Pixel(x,y,c) = output.Pixel(x,y,c);
+
+ bool bWritten = cropped_output.WriteTGAFile( pFname );
+ if ( !bWritten )
+ printf( "Error: failed to save TGA \"%s\"!\n", pFname );
+ else
+ printf( "Ok: successfully saved TGA \"%s\"\n", pFname );
+ }
+
+ // Store these for UV calculation later on
+ s_nHeight = h;
+ s_nWidth = w;
+ return true;
+}
+
+bool PackImages_Rgb_A( char const *pFname, 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 < ImageList.GetNumStrings(); i++)
+ {
+ SequenceFrame &frm=*(ImageList[i]);
+
+ int idxfrm;
+ Sequence::SeqMode_t eMode = frm.m_mapSequences.Key( 0 )->m_eMode;
+ switch ( eMode )
+ {
+ case Sequence::SQM_RGB: idxfrm = 0; bPackingRGBA = false; break;
+ case Sequence::SQM_ALPHA: idxfrm = 1; bPackingRGBA = false; break;
+ case Sequence::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, 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, ImageList.String( i ) ),
+ exit( -1 );
+ }
+
+ if ( cur_column[idxfrm] + frm.m_pImage->Width > output.Width )
+ {
+ // 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->Width > output.Width ) ||
+ ( cur_line[idxfrm] + frm.m_pImage->Height > output.Height ) )
+ {
+ return false; // didn't fit! doh
+ }
+
+ frm.m_XCoord = cur_column[idxfrm];
+ frm.m_YCoord = cur_line[idxfrm];
+
+ if ( pFname ) // don't actually pack the pixel if we're not keeping them
+ {
+ for ( int y = 0; y < frm.m_pImage->Height; y++ )
+ for (int x = 0; x < frm.m_pImage->Width; x++ )
+ for(int c = 0; c < 4; c ++)
+ switch ( eMode )
+ {
+ case Sequence::SQM_RGB: if ( c < 3 ) goto setpx; else break;
+ case Sequence::SQM_ALPHA: if ( c == 3 ) goto setpx; else break;
+ case Sequence::SQM_RGBA: if ( c < 4 ) goto setpx; else 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->Height );
+ cur_column[idxfrm] += frm.m_pImage->Width;
+ 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 ( pFname )
+ {
+ FloatBitMap_t cropped_output( w, h );
+ for(int y=0;y<cropped_output.Height; y++)
+ for(int x=0;x<cropped_output.Width; x++)
+ for(int c=0;c<4;c++)
+ cropped_output.Pixel(x,y,c) = output.Pixel(x,y,c);
+
+ bool bWritten = cropped_output.WriteTGAFile( pFname );
+ if ( !bWritten )
+ printf( "Error: failed to save TGA \"%s\"!\n", pFname );
+ else
+ printf( "Ok: successfully saved TGA \"%s\"\n", pFname );
+ }
+
+ // Store these for UV calculation later on
+ s_nHeight = h;
+ s_nWidth = w;
+ return true;
+}
+
+bool PackImages( char const *pFname, int nWidth )
+{
+ switch ( s_ePackingMode )
+ {
+ case PCKM_FLAT:
+ return PackImages_Flat( pFname, nWidth );
+ case PCKM_RGB_A:
+ return PackImages_Rgb_A( pFname, nWidth );
+ case PCKM_INVALID:
+ default:
+ return false;
+ }
+}
+
+void main(int argc,char **argv)
+{
+ InitCommandLineProgram( argc, argv );
+ if ( argc < 2 || argc > 4 )
+ {
+ printf( "format is 'mksheet sheet.mks [output.sht] [output.tga]'\n" );
+ return;
+ }
+
+ char pMksFileBuf[MAX_PATH];
+ char pShtFileBuf[MAX_PATH];
+ char pTgaFileBuf[MAX_PATH];
+
+ const char *pSourceFile;
+ const char *pShtFile;
+ const char *pTgaFile;
+
+ Q_strncpy( pMksFileBuf, argv[1], sizeof(pMksFileBuf) );
+ Q_DefaultExtension( pMksFileBuf, ".mks", sizeof(pMksFileBuf) );
+ pSourceFile = pMksFileBuf;
+
+ if ( argc < 4 )
+ {
+ Q_StripExtension( pSourceFile, pTgaFileBuf, sizeof(pTgaFileBuf) );
+ Q_SetExtension( pTgaFileBuf, ".tga", sizeof(pTgaFileBuf) );
+ pTgaFile = pTgaFileBuf;
+ }
+ else
+ {
+ pTgaFile = argv[3];
+ }
+
+ if ( argc < 3 )
+ {
+ Q_StripExtension( pSourceFile, pShtFileBuf, sizeof(pShtFileBuf) );
+ Q_SetExtension( pShtFileBuf, ".sht", sizeof(pShtFileBuf) );
+ pShtFile = pShtFileBuf;
+ }
+ else
+ {
+ pShtFile = argv[2];
+ }
+
+ ReportProgress("reading text file",0,0);
+ ReadTextControlFile( pSourceFile );
+ // now, determine best packing
+ 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", s_nWidth, s_nHeight, s_nWidth * s_nHeight );
+
+ bool bPreferThisPack = false;
+
+ int thisSize = s_nHeight * s_nWidth;
+ int thisSquareness = ( s_nWidth == s_nHeight ) ? 1 : ( s_nHeight / s_nWidth + s_nWidth / s_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);
+ }
+
+ s_nWidth = nBestWidth;
+ s_nHeight = nBestSize / nBestWidth;
+ printf( "Best option: %dx%d (%d pixels)%s\n", s_nWidth, s_nHeight, s_nWidth * s_nHeight, ( s_nWidth == s_nHeight ) ? " : square texture" : "" );
+ PackImages( pTgaFile, nBestWidth );
+
+ // now, write ouput
+ ReportProgress("Writing SHT output file",0,0);
+ COutputFile Outfile( pShtFile );
+ if ( Outfile.IsOk() )
+ {
+ Outfile.PutInt( 1 ); // version #
+ Outfile.PutInt( Sequences.Count() );
+ for(int i=0;i<Sequences.Count();i++)
+ {
+ Outfile.PutInt( Sequences[i]->m_nSequenceNumber );
+ Outfile.PutInt( Sequences[i]->m_Clamp );
+ Outfile.PutInt( Sequences[i]->m_Frames.Count() );
+ // write total sequence length
+ float fTotal=0.;
+ for(int j=0;j<Sequences[i]->m_Frames.Count(); j++ )
+ {
+ fTotal += Sequences[i]->m_Frames[j].m_fDisplayTime;
+ }
+ Outfile.PutFloat( fTotal );
+ for(int j=0;j<Sequences[i]->m_Frames.Count(); j++ )
+ {
+ Outfile.PutFloat( Sequences[i]->m_Frames[j].m_fDisplayTime );
+ // output texture coordinates
+ for(int t=0; t<MAX_IMAGES_PER_FRAME; t++)
+ {
+ //xmin
+ Outfile.PutFloat( UCoord( Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_XCoord ) );
+ //ymin
+ Outfile.PutFloat( VCoord( Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_YCoord ) );
+ //xmax
+ Outfile.PutFloat(
+ UCoord( Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_XCoord+
+ Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_pImage->Width-1 ));
+ //ymax
+ Outfile.PutFloat(
+ VCoord( Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_YCoord+
+ Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_pImage->Height-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->Width-1 ),
+ // VCoord( Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_YCoord+Sequences[i]->m_Frames[j].m_pSeqFrame[t]->m_pImage->Height-1 ));
+ }
+ }
+ }
+ printf( "Ok: successfully saved SHT \"%s\"\n", pShtFile );
+ }
+ else
+ {
+ printf( "Error: failed to write SHT \"%s\"!\n", pShtFile );
+ }
+}
diff --git a/utils/mksheet/mksheet.vpc b/utils/mksheet/mksheet.vpc
new file mode 100644
index 0000000..125e48d
--- /dev/null
+++ b/utils/mksheet/mksheet.vpc
@@ -0,0 +1,36 @@
+//-----------------------------------------------------------------------------
+// MKSHEET.VPC
+//
+// Project Script
+//-----------------------------------------------------------------------------
+// ***** AUTO-GENERATED: PLEASE FIXUP MANUALLY BEFORE USING THIS SCRIPT! *****
+
+$Macro SRCDIR "..\.."
+$Macro OUTBINDIR "$SRCDIR\..\game\bin"
+
+$Include "$SRCDIR\vpc_scripts\source_exe_con_base.vpc"
+
+$Configuration
+{
+ $Compiler
+ {
+ $AdditionalIncludeDirectories "$BASE,..\common"
+ }
+}
+
+$Project "Mksheet"
+{
+ $Folder "Source Files"
+ {
+ -$File "$SRCDIR\public\tier0\memoverride.cpp"
+ $File "mksheet.cpp"
+ }
+
+ $Folder "Link Libraries"
+ {
+ $Lib bitmap
+ $Lib mathlib
+ $Lib raytrace
+ $Lib tier2
+ }
+}
diff --git a/utils/mksheet/sheet0.txt b/utils/mksheet/sheet0.txt
new file mode 100644
index 0000000..c91d040
--- /dev/null
+++ b/utils/mksheet/sheet0.txt
@@ -0,0 +1,32 @@
+SEQUENCE 0
+LOOP
+frame testimages\rockettrail000.tga 1
+frame testimages\rockettrail001.tga 1
+frame testimages\rockettrail002.tga 1
+frame testimages\rockettrail003.tga 1
+frame testimages\rockettrail004.tga 1
+frame testimages\rockettrail005.tga 1
+frame testimages\rockettrail006.tga 1
+frame testimages\rockettrail007.tga 1
+frame testimages\rockettrail008.tga 1
+frame testimages\rockettrail009.tga 1
+frame testimages\rockettrail010.tga 1
+frame testimages\rockettrail011.tga 1
+frame testimages\rockettrail012.tga 1
+frame testimages\rockettrail013.tga 1
+frame testimages\rockettrail014.tga 1
+frame testimages\rockettrail015.tga 1
+frame testimages\rockettrail016.tga 1
+frame testimages\rockettrail017.tga 1
+frame testimages\rockettrail018.tga 1
+frame testimages\rockettrail019.tga 1
+frame testimages\rockettrail020.tga 1
+frame testimages\rockettrail021.tga 1
+frame testimages\rockettrail022.tga 1
+frame testimages\rockettrail023.tga 1
+frame testimages\rockettrail024.tga 1
+frame testimages\rockettrail025.tga 1
+
+
+SEQUENCE 1
+ga_frame alpha1.tga alpha2.tga 1
diff --git a/utils/mksheet/testimages/rockettrail000.tga b/utils/mksheet/testimages/rockettrail000.tga
new file mode 100644
index 0000000..7064526
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail000.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail001.tga b/utils/mksheet/testimages/rockettrail001.tga
new file mode 100644
index 0000000..1ff10c5
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail001.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail002.tga b/utils/mksheet/testimages/rockettrail002.tga
new file mode 100644
index 0000000..ddc8b95
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail002.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail003.tga b/utils/mksheet/testimages/rockettrail003.tga
new file mode 100644
index 0000000..4fd0344
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail003.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail004.tga b/utils/mksheet/testimages/rockettrail004.tga
new file mode 100644
index 0000000..8113327
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail004.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail005.tga b/utils/mksheet/testimages/rockettrail005.tga
new file mode 100644
index 0000000..5fa42de
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail005.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail006.tga b/utils/mksheet/testimages/rockettrail006.tga
new file mode 100644
index 0000000..9eac4a8
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail006.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail007.tga b/utils/mksheet/testimages/rockettrail007.tga
new file mode 100644
index 0000000..2709d3b
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail007.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail008.tga b/utils/mksheet/testimages/rockettrail008.tga
new file mode 100644
index 0000000..3a4bbb5
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail008.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail009.tga b/utils/mksheet/testimages/rockettrail009.tga
new file mode 100644
index 0000000..bc4b29d
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail009.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail010.tga b/utils/mksheet/testimages/rockettrail010.tga
new file mode 100644
index 0000000..7274c0f
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail010.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail011.tga b/utils/mksheet/testimages/rockettrail011.tga
new file mode 100644
index 0000000..dddb9e4
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail011.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail012.tga b/utils/mksheet/testimages/rockettrail012.tga
new file mode 100644
index 0000000..41937ab
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail012.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail013.tga b/utils/mksheet/testimages/rockettrail013.tga
new file mode 100644
index 0000000..a890c31
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail013.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail014.tga b/utils/mksheet/testimages/rockettrail014.tga
new file mode 100644
index 0000000..4b9ee1f
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail014.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail015.tga b/utils/mksheet/testimages/rockettrail015.tga
new file mode 100644
index 0000000..c2c344f
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail015.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail016.tga b/utils/mksheet/testimages/rockettrail016.tga
new file mode 100644
index 0000000..22c80f1
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail016.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail017.tga b/utils/mksheet/testimages/rockettrail017.tga
new file mode 100644
index 0000000..81da8ef
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail017.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail018.tga b/utils/mksheet/testimages/rockettrail018.tga
new file mode 100644
index 0000000..c06e4d5
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail018.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail019.tga b/utils/mksheet/testimages/rockettrail019.tga
new file mode 100644
index 0000000..f787aed
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail019.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail020.tga b/utils/mksheet/testimages/rockettrail020.tga
new file mode 100644
index 0000000..cf959bc
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail020.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail021.tga b/utils/mksheet/testimages/rockettrail021.tga
new file mode 100644
index 0000000..4e9adbe
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail021.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail022.tga b/utils/mksheet/testimages/rockettrail022.tga
new file mode 100644
index 0000000..4f325d8
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail022.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail023.tga b/utils/mksheet/testimages/rockettrail023.tga
new file mode 100644
index 0000000..be85afa
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail023.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail024.tga b/utils/mksheet/testimages/rockettrail024.tga
new file mode 100644
index 0000000..be85afa
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail024.tga
Binary files differ
diff --git a/utils/mksheet/testimages/rockettrail025.tga b/utils/mksheet/testimages/rockettrail025.tga
new file mode 100644
index 0000000..be85afa
--- /dev/null
+++ b/utils/mksheet/testimages/rockettrail025.tga
Binary files differ