2017-01-20 08:36:52 -05:00
# include "STDInclude.hpp"
2016-01-22 05:59:43 -05:00
2019-02-01 16:16:42 -05:00
# define IW4X_TECHSET_VERSION "0"
2016-01-22 05:59:43 -05:00
namespace Assets
{
2019-02-01 16:16:42 -05:00
void IMaterialTechniqueSet : : load ( Game : : XAssetHeader * header , const std : : string & name , Components : : ZoneBuilder : : Zone * builder )
{
if ( ! header - > data ) this - > loadNative ( header , name , builder ) ; // Check if there is a native one
if ( ! header - > data ) this - > loadBinary ( header , name , builder ) ; // Check if we need to import a new one into the game
}
void IMaterialTechniqueSet : : loadNative ( Game : : XAssetHeader * header , const std : : string & name , Components : : ZoneBuilder : : Zone * /*builder*/ )
{
header - > techniqueSet = Components : : AssetHandler : : FindOriginalAsset ( this - > getType ( ) , name . data ( ) ) . techniqueSet ;
}
void IMaterialTechniqueSet : : loadBinaryTechnique ( Game : : MaterialTechnique * * tech , const std : : string & name , Components : : ZoneBuilder : : Zone * builder )
{
AssertSize ( Game : : MaterialPass , 20 ) ;
Components : : FileSystem : : File techFile ( Utils : : String : : VA ( " techniques/%s.iw4xTech " , name . data ( ) ) ) ;
if ( ! techFile . exists ( ) ) {
* tech = nullptr ;
Components : : Logger : : Print ( " Warning: Missing technique '%s' \n " , name . data ( ) ) ;
return ;
}
Utils : : Stream : : Reader reader ( builder - > getAllocator ( ) , techFile . getBuffer ( ) ) ;
char * magic = reader . readArray < char > ( 8 ) ;
if ( std : : memcmp ( magic , " IW4xTECH " , 8 ) )
{
Components : : Logger : : Error ( 0 , " Reading technique '%s' failed, header is invalid! " , name . data ( ) ) ;
}
std : : string version ;
version . push_back ( reader . read < char > ( ) ) ;
if ( version ! = IW4X_TECHSET_VERSION )
{
Components : : Logger : : Error ( " Reading technique '%s' failed, expected version is %d, but it was %d! " , name . data ( ) , atoi ( IW4X_TECHSET_VERSION ) , atoi ( version . data ( ) ) ) ;
}
unsigned short flags = reader . read < unsigned short > ( ) ;
unsigned short passCount = reader . read < unsigned short > ( ) ;
Game : : MaterialTechnique * asset = ( Game : : MaterialTechnique * ) builder - > getAllocator ( ) - > allocateArray < unsigned char > ( sizeof ( Game : : MaterialTechnique ) + ( sizeof ( Game : : MaterialPass ) * ( passCount - 1 ) ) ) ;
asset - > name = builder - > getAllocator ( ) - > duplicateString ( name ) ;
asset - > flags = flags ;
asset - > passCount = passCount ;
Game : : MaterialPass * passes = reader . readArray < Game : : MaterialPass > ( passCount ) ;
std : : memcpy ( asset - > passArray , passes , sizeof ( Game : : MaterialPass ) * passCount ) ;
for ( unsigned short i = 0 ; i < asset - > passCount ; i + + )
{
Game : : MaterialPass * pass = & asset - > passArray [ i ] ;
if ( pass - > vertexDecl )
{
const char * declName = reader . readCString ( ) ;
pass - > vertexDecl = Components : : AssetHandler : : FindAssetForZone ( Game : : XAssetType : : ASSET_TYPE_VERTEXDECL , declName , builder ) . vertexDecl ;
}
if ( pass - > vertexShader )
{
const char * vsName = reader . readCString ( ) ;
pass - > vertexShader = Components : : AssetHandler : : FindAssetForZone ( Game : : XAssetType : : ASSET_TYPE_VERTEXSHADER , vsName , builder ) . vertexShader ;
}
if ( pass - > pixelShader )
{
const char * psName = reader . readCString ( ) ;
pass - > pixelShader = Components : : AssetHandler : : FindAssetForZone ( Game : : XAssetType : : ASSET_TYPE_PIXELSHADER , psName , builder ) . pixelShader ;
}
pass - > args = reader . readArray < Game : : MaterialShaderArgument > ( pass - > perPrimArgCount + pass - > perObjArgCount + pass - > stableArgCount ) ;
for ( int j = 0 ; j < pass - > perPrimArgCount + pass - > perObjArgCount + pass - > stableArgCount ; j + + )
{
if ( pass - > args [ j ] . type = = 1 | | pass - > args [ j ] . type = = 7 )
{
pass - > args [ j ] . u . literalConst = reader . readArray < float > ( 4 ) ;
}
if ( pass - > args [ j ] . type = = 3 | | pass - > args [ j ] . type = = 5 )
{
pass - > args [ j ] . u . codeConst . index = * reader . readObject < unsigned short > ( ) ;
pass - > args [ j ] . u . codeConst . firstRow = * reader . readObject < unsigned char > ( ) ;
pass - > args [ j ] . u . codeConst . rowCount = * reader . readObject < unsigned char > ( ) ;
}
}
}
* tech = asset ;
}
void IMaterialTechniqueSet : : loadBinary ( Game : : XAssetHeader * header , const std : : string & name , Components : : ZoneBuilder : : Zone * builder )
{
Components : : FileSystem : : File tsFile ( Utils : : String : : VA ( " techsets/%s.iw4xTS " , name . data ( ) ) ) ;
if ( ! tsFile . exists ( ) ) return ;
Utils : : Stream : : Reader reader ( builder - > getAllocator ( ) , tsFile . getBuffer ( ) ) ;
char * magic = reader . readArray < char > ( 8 ) ;
if ( std : : memcmp ( magic , " IW4xTSET " , 8 ) )
{
Components : : Logger : : Error ( 0 , " Reading techset '%s' failed, header is invalid! " , name . data ( ) ) ;
}
std : : string version ;
version . push_back ( reader . read < char > ( ) ) ;
if ( version ! = IW4X_TECHSET_VERSION )
{
Components : : Logger : : Error ( " Reading techset '%s' failed, expected version is %d, but it was %d! " , name . data ( ) , atoi ( IW4X_TECHSET_VERSION ) , atoi ( version . data ( ) ) ) ;
}
Game : : MaterialTechniqueSet * asset = reader . readObject < Game : : MaterialTechniqueSet > ( ) ;
if ( asset - > name )
{
asset - > name = reader . readCString ( ) ;
}
for ( int i = 0 ; i < 48 ; i + + )
{
if ( asset - > techniques [ i ] )
{
const char * techName = reader . readCString ( ) ;
this - > loadBinaryTechnique ( & asset - > techniques [ i ] , techName , builder ) ;
}
}
header - > techniqueSet = asset ;
}
2016-11-20 08:09:07 -05:00
void IMaterialTechniqueSet : : mark ( Game : : XAssetHeader header , Components : : ZoneBuilder : : Zone * builder )
2019-02-01 16:16:42 -05:00
{
2016-12-21 11:26:16 -05:00
Game : : MaterialTechniqueSet * asset = header . techniqueSet ;
2016-01-22 05:59:43 -05:00
2016-09-16 18:14:59 -04:00
for ( int i = 0 ; i < ARRAYSIZE ( Game : : MaterialTechniqueSet : : techniques ) ; + + i )
2016-01-22 05:59:43 -05:00
{
Game : : MaterialTechnique * technique = asset - > techniques [ i ] ;
if ( ! technique ) continue ;
2017-04-22 15:47:04 -04:00
for ( short j = 0 ; j < technique - > passCount ; + + j )
2016-01-22 05:59:43 -05:00
{
2017-04-22 15:47:04 -04:00
Game : : MaterialPass * pass = & technique - > passArray [ j ] ;
2016-01-22 05:59:43 -05:00
if ( pass - > vertexDecl )
{
2016-12-23 15:01:56 -05:00
builder - > loadAsset ( Game : : XAssetType : : ASSET_TYPE_VERTEXDECL , pass - > vertexDecl ) ;
2016-01-22 05:59:43 -05:00
}
if ( pass - > vertexShader )
{
2016-12-23 15:01:56 -05:00
builder - > loadAsset ( Game : : XAssetType : : ASSET_TYPE_VERTEXSHADER , pass - > vertexShader ) ;
2016-01-22 05:59:43 -05:00
}
if ( pass - > pixelShader )
{
2016-12-23 15:01:56 -05:00
builder - > loadAsset ( Game : : XAssetType : : ASSET_TYPE_PIXELSHADER , pass - > pixelShader ) ;
2016-01-22 05:59:43 -05:00
}
}
}
}
2016-11-20 08:09:07 -05:00
void IMaterialTechniqueSet : : save ( Game : : XAssetHeader header , Components : : ZoneBuilder : : Zone * builder )
2016-01-22 05:59:43 -05:00
{
2016-11-20 08:09:07 -05:00
AssertSize ( Game : : MaterialTechniqueSet , 204 ) ;
2016-01-22 05:59:43 -05:00
2016-11-20 08:09:07 -05:00
Utils : : Stream * buffer = builder - > getBuffer ( ) ;
2016-12-21 11:26:16 -05:00
Game : : MaterialTechniqueSet * asset = header . techniqueSet ;
2016-11-20 08:09:07 -05:00
Game : : MaterialTechniqueSet * dest = buffer - > dest < Game : : MaterialTechniqueSet > ( ) ;
buffer - > save ( asset ) ;
2016-01-22 05:59:43 -05:00
2016-11-20 08:09:07 -05:00
buffer - > pushBlock ( Game : : XFILE_BLOCK_VIRTUAL ) ;
2016-01-22 05:59:43 -05:00
if ( asset - > name )
{
2016-11-20 08:09:07 -05:00
buffer - > saveString ( builder - > getAssetName ( this - > getType ( ) , asset - > name ) ) ;
2016-06-10 07:52:55 -04:00
Utils : : Stream : : ClearPointer ( & dest - > name ) ;
2016-01-22 05:59:43 -05:00
}
// Save_MaterialTechniquePtrArray
2016-09-16 18:14:59 -04:00
static_assert ( ARRAYSIZE ( Game : : MaterialTechniqueSet : : techniques ) = = 48 , " Techniques array invalid! " ) ;
2016-01-22 05:59:43 -05:00
2016-09-16 18:14:59 -04:00
for ( int i = 0 ; i < ARRAYSIZE ( Game : : MaterialTechniqueSet : : techniques ) ; + + i )
2016-01-22 05:59:43 -05:00
{
Game : : MaterialTechnique * technique = asset - > techniques [ i ] ;
if ( technique )
{
2016-11-20 08:09:07 -05:00
if ( builder - > hasPointer ( technique ) )
2016-01-22 07:18:26 -05:00
{
2016-11-20 08:09:07 -05:00
dest - > techniques [ i ] = builder - > getPointer ( technique ) ;
2016-01-22 07:18:26 -05:00
}
else
2016-01-22 05:59:43 -05:00
{
2016-01-22 07:18:26 -05:00
// Size-check is obsolete, as the structure is dynamic
2016-11-20 08:09:07 -05:00
buffer - > align ( Utils : : Stream : : ALIGN_4 ) ;
builder - > storePointer ( technique ) ;
2016-01-22 05:59:43 -05:00
2016-11-20 08:09:07 -05:00
Game : : MaterialTechnique * destTechnique = buffer - > dest < Game : : MaterialTechnique > ( ) ;
buffer - > save ( technique , 8 ) ;
2016-01-22 05:59:43 -05:00
2016-01-22 07:18:26 -05:00
// Save_MaterialPassArray
2016-11-20 08:09:07 -05:00
Game : : MaterialPass * destPasses = buffer - > dest < Game : : MaterialPass > ( ) ;
2017-04-22 15:47:04 -04:00
buffer - > saveArray ( technique - > passArray , technique - > passCount ) ;
2016-10-09 06:02:17 -04:00
2017-04-22 15:47:04 -04:00
for ( short j = 0 ; j < technique - > passCount ; + + j )
2016-01-22 05:59:43 -05:00
{
2016-11-20 08:09:07 -05:00
AssertSize ( Game : : MaterialPass , 20 ) ;
2016-01-22 07:18:26 -05:00
2016-10-09 06:02:17 -04:00
Game : : MaterialPass * destPass = & destPasses [ j ] ;
2017-04-22 15:47:04 -04:00
Game : : MaterialPass * pass = & technique - > passArray [ j ] ;
2016-01-22 07:18:26 -05:00
if ( pass - > vertexDecl )
{
2016-12-23 01:42:56 -05:00
destPass - > vertexDecl = builder - > saveSubAsset ( Game : : XAssetType : : ASSET_TYPE_VERTEXDECL , pass - > vertexDecl ) . vertexDecl ;
2016-01-22 07:18:26 -05:00
}
if ( pass - > vertexShader )
{
2016-12-23 01:42:56 -05:00
destPass - > vertexShader = builder - > saveSubAsset ( Game : : XAssetType : : ASSET_TYPE_VERTEXSHADER , pass - > vertexShader ) . vertexShader ;
2016-01-22 07:18:26 -05:00
}
if ( pass - > pixelShader )
{
2016-12-23 01:42:56 -05:00
destPass - > pixelShader = builder - > saveSubAsset ( Game : : XAssetType : : ASSET_TYPE_PIXELSHADER , pass - > pixelShader ) . pixelShader ;
2016-01-22 07:18:26 -05:00
}
2017-04-22 15:47:04 -04:00
if ( pass - > args )
2016-01-22 07:18:26 -05:00
{
2016-11-20 08:09:07 -05:00
buffer - > align ( Utils : : Stream : : ALIGN_4 ) ;
2017-05-29 04:54:20 -04:00
Game : : MaterialShaderArgument * destArgs = buffer - > dest < Game : : MaterialShaderArgument > ( ) ;
2017-04-22 15:47:04 -04:00
buffer - > saveArray ( pass - > args , pass - > perPrimArgCount + pass - > perObjArgCount + pass - > stableArgCount ) ;
2017-05-29 04:54:20 -04:00
2017-06-14 06:06:04 -04:00
for ( int k = 0 ; k < pass - > perPrimArgCount + pass - > perObjArgCount + pass - > stableArgCount ; + + k )
2017-05-29 04:54:20 -04:00
{
Game : : MaterialShaderArgument * arg = & pass - > args [ k ] ;
Game : : MaterialShaderArgument * destArg = & destArgs [ k ] ;
2017-06-14 06:06:04 -04:00
if ( arg - > type = = 1 | | arg - > type = = 7 )
2017-05-29 04:54:20 -04:00
{
if ( builder - > hasPointer ( arg - > u . literalConst ) )
{
destArg - > u . literalConst = builder - > getPointer ( arg - > u . literalConst ) ;
}
else
{
buffer - > align ( Utils : : Stream : : ALIGN_4 ) ;
builder - > storePointer ( arg - > u . literalConst ) ;
buffer - > saveArray ( arg - > u . literalConst , 4 ) ;
Utils : : Stream : : ClearPointer ( & destArg - > u . literalConst ) ;
}
}
}
2017-04-22 15:47:04 -04:00
Utils : : Stream : : ClearPointer ( & destPass - > args ) ;
2016-01-22 07:18:26 -05:00
}
2016-01-22 05:59:43 -05:00
}
2016-01-22 07:18:26 -05:00
if ( technique - > name )
2016-01-22 05:59:43 -05:00
{
2016-11-20 08:09:07 -05:00
buffer - > saveString ( technique - > name ) ;
2016-06-10 07:52:55 -04:00
Utils : : Stream : : ClearPointer ( & destTechnique - > name ) ;
2016-01-22 05:59:43 -05:00
}
2016-06-10 07:52:55 -04:00
Utils : : Stream : : ClearPointer ( & dest - > techniques [ i ] ) ;
2016-01-22 05:59:43 -05:00
}
}
}
2016-11-20 08:09:07 -05:00
buffer - > popBlock ( ) ;
2016-01-22 05:59:43 -05:00
}
}