Penumbra/Penumbra.GameData/Files/MtrlFile.Write.cs

116 lines
No EOL
3.8 KiB
C#

using System;
using System.IO;
using System.Linq;
using System.Text;
namespace Penumbra.GameData.Files;
public partial class MtrlFile
{
public byte[] Write()
{
using var stream = new MemoryStream();
using( var w = new BinaryWriter( stream ) )
{
const int materialHeaderSize = 4 + 2 + 2 + 2 + 2 + 1 + 1 + 1 + 1;
w.BaseStream.Seek( materialHeaderSize, SeekOrigin.Begin );
ushort cumulativeStringOffset = 0;
foreach( var texture in Textures )
{
w.Write( cumulativeStringOffset );
w.Write( texture.Flags );
cumulativeStringOffset += ( ushort )( texture.Path.Length + 1 );
}
foreach( var set in UvSets )
{
w.Write( cumulativeStringOffset );
w.Write( set.Index );
cumulativeStringOffset += ( ushort )( set.Name.Length + 1 );
}
foreach( var set in ColorSets )
{
w.Write( cumulativeStringOffset );
w.Write( set.Index );
cumulativeStringOffset += ( ushort )( set.Name.Length + 1 );
}
foreach( var text in Textures.Select( t => t.Path )
.Concat( UvSets.Select( c => c.Name ) )
.Concat( ColorSets.Select( c => c.Name ) )
.Append( ShaderPackage.Name ) )
{
w.Write( Encoding.UTF8.GetBytes( text ) );
w.Write( ( byte )'\0' );
}
w.Write( AdditionalData );
var dataSetSize = 0;
foreach( var row in ColorSets.Where( c => c.HasRows ).Select( c => c.Rows ) )
{
var span = row.AsBytes();
w.Write( span );
dataSetSize += span.Length;
}
foreach( var row in ColorDyeSets.Select( c => c.Rows ) )
{
var span = row.AsBytes();
w.Write( span );
dataSetSize += span.Length;
}
w.Write( ( ushort )( ShaderPackage.ShaderValues.Length * 4 ) );
w.Write( ( ushort )ShaderPackage.ShaderKeys.Length );
w.Write( ( ushort )ShaderPackage.Constants.Length );
w.Write( ( ushort )ShaderPackage.Samplers.Length );
w.Write( ShaderPackage.Flags );
foreach( var key in ShaderPackage.ShaderKeys )
{
w.Write( key.Category );
w.Write( key.Value );
}
foreach( var constant in ShaderPackage.Constants )
{
w.Write( constant.Id );
w.Write( constant.Value );
}
foreach( var sampler in ShaderPackage.Samplers )
{
w.Write( sampler.SamplerId );
w.Write( sampler.Flags );
w.Write( sampler.TextureIndex );
w.Write( ( ushort )0 );
w.Write( ( byte )0 );
}
foreach( var value in ShaderPackage.ShaderValues )
{
w.Write( value );
}
WriteHeader( w, ( ushort )w.BaseStream.Position, dataSetSize, cumulativeStringOffset );
}
return stream.ToArray();
}
private void WriteHeader( BinaryWriter w, ushort fileSize, int dataSetSize, ushort shaderPackageNameOffset )
{
w.BaseStream.Seek( 0, SeekOrigin.Begin );
w.Write( Version );
w.Write( fileSize );
w.Write( ( ushort )dataSetSize );
w.Write( ( ushort )( shaderPackageNameOffset + ShaderPackage.Name.Length + 1 ) );
w.Write( shaderPackageNameOffset );
w.Write( ( byte )Textures.Length );
w.Write( ( byte )UvSets.Length );
w.Write( ( byte )ColorSets.Length );
w.Write( ( byte )AdditionalData.Length );
}
}