Add support for sprites with alpha mask

- Sprites with alpha mask can now be viewed and exported with transparency
- Added hotkeys to control display of an alpha mask  on the preview tab
- Added an option to the export settings to enable/disable export with alpha mask as well
- Prevented texture2D preview options from being changed with hotkeys outside of texture preview (e.g. when some other asset is selected)
This commit is contained in:
VaDiM 2022-11-21 01:52:40 +03:00
parent 7fa5b4f355
commit ea09a8de64
9 changed files with 208 additions and 104 deletions

View File

@ -1,83 +1,83 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFrameworks>net472;net6.0-windows</TargetFrameworks> <TargetFrameworks>net472;net6.0-windows</TargetFrameworks>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>Resources\as.ico</ApplicationIcon> <ApplicationIcon>Resources\as.ico</ApplicationIcon>
<AssemblyTitle>AssetStudio Mod by VaDiM</AssemblyTitle> <AssemblyTitle>AssetStudio Mod by VaDiM</AssemblyTitle>
<Version>0.16.47.1</Version> <Version>0.16.47.1</Version>
<Copyright>Copyright © Perfare 2018-2022</Copyright> <Copyright>Copyright © Perfare 2018-2022</Copyright>
<DebugType>embedded</DebugType> <DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\AssetStudioUtility\AssetStudioUtility.csproj" /> <ProjectReference Include="..\AssetStudioUtility\AssetStudioUtility.csproj" />
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj" /> <ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Properties\Settings.settings"> <EmbeddedResource Update="Properties\Resources.resx">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</None> </EmbeddedResource>
<Compile Update="Properties\Settings.Designer.cs"> <Compile Update="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTime>True</DesignTime>
</Compile> </Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx"> <ContentWithTargetPath Include="Libraries\x86\fmod.dll">
<Generator>ResXFileCodeGenerator</Generator> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <TargetPath>x86\fmod.dll</TargetPath>
</EmbeddedResource> </ContentWithTargetPath>
<Compile Update="Properties\Resources.Designer.cs"> <ContentWithTargetPath Include="Libraries\x64\fmod.dll">
<AutoGen>True</AutoGen> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<DependentUpon>Resources.resx</DependentUpon> <TargetPath>x64\fmod.dll</TargetPath>
<DesignTime>True</DesignTime> </ContentWithTargetPath>
</Compile> </ItemGroup>
</ItemGroup>
<ItemGroup> <ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
<ContentWithTargetPath Include="Libraries\x86\fmod.dll"> <PackageReference Include="OpenTK" Version="4.6.7" />
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <Reference Include="OpenTK.WinForms">
<TargetPath>x86\fmod.dll</TargetPath> <HintPath>Libraries\OpenTK.WinForms.dll</HintPath>
</ContentWithTargetPath> </Reference>
<ContentWithTargetPath Include="Libraries\x64\fmod.dll"> </ItemGroup>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>x64\fmod.dll</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' "> <ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<PackageReference Include="OpenTK" Version="4.6.7" /> <PackageReference Include="OpenTK" Version="3.1.0" />
<Reference Include="OpenTK.WinForms"> <PackageReference Include="OpenTK.GLControl" Version="3.1.0" />
<HintPath>Libraries\OpenTK.WinForms.dll</HintPath> </ItemGroup>
</Reference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' "> <ItemGroup>
<PackageReference Include="OpenTK" Version="3.1.0" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="OpenTK.GLControl" Version="3.1.0" /> </ItemGroup>
</ItemGroup>
<ItemGroup> <Target Name="CopyExtraFiles" AfterTargets="AfterBuild">
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
</ItemGroup> <Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
</Target>
<Target Name="CopyExtraFiles" AfterTargets="AfterBuild"> <Target Name="PublishExtraFiles" AfterTargets="Publish">
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" /> <Copy SourceFiles="$(TargetDir)x86\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" /> <Copy SourceFiles="$(TargetDir)x64\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" /> <Copy SourceFiles="$(TargetDir)x86\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" /> <Copy SourceFiles="$(TargetDir)x64\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
</Target> </Target>
<Target Name="PublishExtraFiles" AfterTargets="Publish">
<Copy SourceFiles="$(TargetDir)x86\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
<Copy SourceFiles="$(TargetDir)x64\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
<Copy SourceFiles="$(TargetDir)x86\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
<Copy SourceFiles="$(TargetDir)x64\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
</Target>
</Project> </Project>

View File

@ -43,6 +43,10 @@ namespace AssetStudioGUI
private uint FMODlenms; private uint FMODlenms;
private float FMODVolume = 0.8f; private float FMODVolume = 0.8f;
#region SpriteControl
private SpriteMaskMode spriteMaskVisibleMode = SpriteMaskMode.On;
#endregion
#region TexControl #region TexControl
private static char[] textureChannelNames = new[] { 'B', 'G', 'R', 'A' }; private static char[] textureChannelNames = new[] { 'B', 'G', 'R', 'A' };
private bool[] textureChannels = new[] { true, true, true, true }; private bool[] textureChannels = new[] { true, true, true, true };
@ -315,24 +319,41 @@ namespace AssetStudioGUI
if (e.Control) if (e.Control)
{ {
var need = false; var need = false;
switch (e.KeyCode) if (lastSelectedItem.Type == ClassIDType.Texture2D)
{ {
case Keys.B: switch (e.KeyCode)
textureChannels[0] = !textureChannels[0]; {
need = true; case Keys.B:
break; textureChannels[0] = !textureChannels[0];
case Keys.G: need = true;
textureChannels[1] = !textureChannels[1]; break;
need = true; case Keys.G:
break; textureChannels[1] = !textureChannels[1];
case Keys.R: need = true;
textureChannels[2] = !textureChannels[2]; break;
need = true; case Keys.R:
break; textureChannels[2] = !textureChannels[2];
case Keys.A: need = true;
textureChannels[3] = !textureChannels[3]; break;
need = true; case Keys.A:
break; textureChannels[3] = !textureChannels[3];
need = true;
break;
}
}
else if (lastSelectedItem.Type == ClassIDType.Sprite && !((Sprite)lastSelectedItem.Asset).m_RD.alphaTexture.IsNull)
{
switch (e.KeyCode)
{
case Keys.A:
spriteMaskVisibleMode = spriteMaskVisibleMode == SpriteMaskMode.On ? SpriteMaskMode.Off : SpriteMaskMode.On;
need = true;
break;
case Keys.M:
spriteMaskVisibleMode = spriteMaskVisibleMode == SpriteMaskMode.MaskOnly ? SpriteMaskMode.On : SpriteMaskMode.MaskOnly;
need = true;
break;
}
} }
if (need) if (need)
{ {
@ -1170,13 +1191,19 @@ namespace AssetStudioGUI
private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite) private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
{ {
var image = m_Sprite.GetImage(); var image = m_Sprite.GetImage(spriteMaskVisibleMode);
if (image != null) if (image != null)
{ {
var bitmap = new DirectBitmap(image.ConvertToBytes(), image.Width, image.Height); var bitmap = new DirectBitmap(image.ConvertToBytes(), image.Width, image.Height);
image.Dispose(); image.Dispose();
assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n"; assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n";
PreviewTexture(bitmap); PreviewTexture(bitmap);
if (!m_Sprite.m_RD.alphaTexture.IsNull)
{
assetItem.InfoText += $"Alpha Mask: {spriteMaskVisibleMode}\n";
StatusStripUpdate("'Ctrl'+'A' - Enable/Disable alpha mask usage. 'Ctrl'+'M' - Show alpha mask only.");
}
} }
else else
{ {

View File

@ -32,6 +32,7 @@
this.OKbutton = new System.Windows.Forms.Button(); this.OKbutton = new System.Windows.Forms.Button();
this.Cancel = new System.Windows.Forms.Button(); this.Cancel = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox(); this.groupBox1 = new System.Windows.Forms.GroupBox();
this.exportSpriteWithAlphaMask = new System.Windows.Forms.CheckBox();
this.openAfterExport = new System.Windows.Forms.CheckBox(); this.openAfterExport = new System.Windows.Forms.CheckBox();
this.restoreExtensionName = new System.Windows.Forms.CheckBox(); this.restoreExtensionName = new System.Windows.Forms.CheckBox();
this.assetGroupOptions = new System.Windows.Forms.ComboBox(); this.assetGroupOptions = new System.Windows.Forms.ComboBox();
@ -94,6 +95,7 @@
// groupBox1 // groupBox1
// //
this.groupBox1.AutoSize = true; this.groupBox1.AutoSize = true;
this.groupBox1.Controls.Add(this.exportSpriteWithAlphaMask);
this.groupBox1.Controls.Add(this.openAfterExport); this.groupBox1.Controls.Add(this.openAfterExport);
this.groupBox1.Controls.Add(this.restoreExtensionName); this.groupBox1.Controls.Add(this.restoreExtensionName);
this.groupBox1.Controls.Add(this.assetGroupOptions); this.groupBox1.Controls.Add(this.assetGroupOptions);
@ -108,12 +110,24 @@
this.groupBox1.TabStop = false; this.groupBox1.TabStop = false;
this.groupBox1.Text = "Export"; this.groupBox1.Text = "Export";
// //
// exportSpriteWithAlphaMask
//
this.exportSpriteWithAlphaMask.AutoSize = true;
this.exportSpriteWithAlphaMask.Checked = true;
this.exportSpriteWithAlphaMask.CheckState = System.Windows.Forms.CheckState.Checked;
this.exportSpriteWithAlphaMask.Location = new System.Drawing.Point(6, 150);
this.exportSpriteWithAlphaMask.Name = "exportSpriteWithAlphaMask";
this.exportSpriteWithAlphaMask.Size = new System.Drawing.Size(205, 17);
this.exportSpriteWithAlphaMask.TabIndex = 11;
this.exportSpriteWithAlphaMask.Text = "Export sprites with alpha mask applied";
this.exportSpriteWithAlphaMask.UseVisualStyleBackColor = true;
//
// openAfterExport // openAfterExport
// //
this.openAfterExport.AutoSize = true; this.openAfterExport.AutoSize = true;
this.openAfterExport.Checked = true; this.openAfterExport.Checked = true;
this.openAfterExport.CheckState = System.Windows.Forms.CheckState.Checked; this.openAfterExport.CheckState = System.Windows.Forms.CheckState.Checked;
this.openAfterExport.Location = new System.Drawing.Point(6, 173); this.openAfterExport.Location = new System.Drawing.Point(6, 196);
this.openAfterExport.Name = "openAfterExport"; this.openAfterExport.Name = "openAfterExport";
this.openAfterExport.Size = new System.Drawing.Size(137, 17); this.openAfterExport.Size = new System.Drawing.Size(137, 17);
this.openAfterExport.TabIndex = 10; this.openAfterExport.TabIndex = 10;
@ -160,7 +174,7 @@
this.convertAudio.AutoSize = true; this.convertAudio.AutoSize = true;
this.convertAudio.Checked = true; this.convertAudio.Checked = true;
this.convertAudio.CheckState = System.Windows.Forms.CheckState.Checked; this.convertAudio.CheckState = System.Windows.Forms.CheckState.Checked;
this.convertAudio.Location = new System.Drawing.Point(6, 150); this.convertAudio.Location = new System.Drawing.Point(6, 173);
this.convertAudio.Name = "convertAudio"; this.convertAudio.Name = "convertAudio";
this.convertAudio.Size = new System.Drawing.Size(179, 17); this.convertAudio.Size = new System.Drawing.Size(179, 17);
this.convertAudio.TabIndex = 6; this.convertAudio.TabIndex = 6;
@ -531,5 +545,6 @@
private System.Windows.Forms.CheckBox openAfterExport; private System.Windows.Forms.CheckBox openAfterExport;
private System.Windows.Forms.CheckBox exportAllUvsAsDiffuseMaps; private System.Windows.Forms.CheckBox exportAllUvsAsDiffuseMaps;
private System.Windows.Forms.ToolTip exportUvsTooltip; private System.Windows.Forms.ToolTip exportUvsTooltip;
private System.Windows.Forms.CheckBox exportSpriteWithAlphaMask;
} }
} }

View File

@ -12,6 +12,7 @@ namespace AssetStudioGUI
assetGroupOptions.SelectedIndex = Properties.Settings.Default.assetGroupOption; assetGroupOptions.SelectedIndex = Properties.Settings.Default.assetGroupOption;
restoreExtensionName.Checked = Properties.Settings.Default.restoreExtensionName; restoreExtensionName.Checked = Properties.Settings.Default.restoreExtensionName;
converttexture.Checked = Properties.Settings.Default.convertTexture; converttexture.Checked = Properties.Settings.Default.convertTexture;
exportSpriteWithAlphaMask.Checked = Properties.Settings.Default.exportSpriteWithMask;
convertAudio.Checked = Properties.Settings.Default.convertAudio; convertAudio.Checked = Properties.Settings.Default.convertAudio;
var str = Properties.Settings.Default.convertType.ToString(); var str = Properties.Settings.Default.convertType.ToString();
foreach (Control c in panel1.Controls) foreach (Control c in panel1.Controls)
@ -43,6 +44,7 @@ namespace AssetStudioGUI
Properties.Settings.Default.assetGroupOption = assetGroupOptions.SelectedIndex; Properties.Settings.Default.assetGroupOption = assetGroupOptions.SelectedIndex;
Properties.Settings.Default.restoreExtensionName = restoreExtensionName.Checked; Properties.Settings.Default.restoreExtensionName = restoreExtensionName.Checked;
Properties.Settings.Default.convertTexture = converttexture.Checked; Properties.Settings.Default.convertTexture = converttexture.Checked;
Properties.Settings.Default.exportSpriteWithMask = exportSpriteWithAlphaMask.Checked;
Properties.Settings.Default.convertAudio = convertAudio.Checked; Properties.Settings.Default.convertAudio = convertAudio.Checked;
foreach (Control c in panel1.Controls) foreach (Control c in panel1.Controls)
{ {
@ -75,6 +77,5 @@ namespace AssetStudioGUI
DialogResult = DialogResult.Cancel; DialogResult = DialogResult.Cancel;
Close(); Close();
} }
} }
} }

View File

@ -120,7 +120,4 @@
<metadata name="exportUvsTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="exportUvsTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value> <value>17, 17</value>
</metadata> </metadata>
<metadata name="exportUvsTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root> </root>

View File

@ -231,9 +231,10 @@ namespace AssetStudioGUI
public static bool ExportSprite(AssetItem item, string exportPath) public static bool ExportSprite(AssetItem item, string exportPath)
{ {
var type = Properties.Settings.Default.convertType; var type = Properties.Settings.Default.convertType;
var alphaMask = Properties.Settings.Default.exportSpriteWithMask ? SpriteMaskMode.On : SpriteMaskMode.Off;
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath)) if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
return false; return false;
var image = ((Sprite)item.Asset).GetImage(); var image = ((Sprite)item.Asset).GetImage(alphaMask);
if (image != null) if (image != null)
{ {
using (image) using (image)

View File

@ -1,10 +1,10 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// 此代码由工具生成。 // This code was generated by a tool.
// 运行时版本:4.0.30319.42000 // Runtime Version:4.0.30319.42000
// //
// 对此文件的更改可能会导致不正确的行为,并且如果 // Changes to this file may cause incorrect behavior and will be lost if
// 重新生成代码,这些更改将会丢失。 // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -12,7 +12,7 @@ namespace AssetStudioGUI.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.1.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@ -274,5 +274,17 @@ namespace AssetStudioGUI.Properties {
this["exportAllUvsAsDiffuseMaps"] = value; this["exportAllUvsAsDiffuseMaps"] = value;
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool exportSpriteWithMask {
get {
return ((bool)(this["exportSpriteWithMask"]));
}
set {
this["exportSpriteWithMask"] = value;
}
}
} }
} }

View File

@ -65,5 +65,8 @@
<Setting Name="exportAllUvsAsDiffuseMaps" Type="System.Boolean" Scope="User"> <Setting Name="exportAllUvsAsDiffuseMaps" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value> <Value Profile="(Default)">False</Value>
</Setting> </Setting>
<Setting Name="exportSpriteWithMask" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
</Settings> </Settings>
</SettingsFile> </SettingsFile>

View File

@ -11,9 +11,16 @@ using System.Numerics;
namespace AssetStudio namespace AssetStudio
{ {
public enum SpriteMaskMode
{
Off,
On,
MaskOnly
}
public static class SpriteHelper public static class SpriteHelper
{ {
public static Image<Bgra32> GetImage(this Sprite m_Sprite) public static Image<Bgra32> GetImage(this Sprite m_Sprite, SpriteMaskMode spriteMaskVisibleMode = SpriteMaskMode.On)
{ {
if (m_Sprite.m_SpriteAtlas != null && m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlas)) if (m_Sprite.m_SpriteAtlas != null && m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlas))
{ {
@ -24,7 +31,26 @@ namespace AssetStudio
} }
else else
{ {
if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D)) if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D) && m_Sprite.m_RD.alphaTexture.TryGet(out var m_AlphaTexture2D) && spriteMaskVisibleMode != SpriteMaskMode.Off)
{
var tex = CutImage(m_Sprite, m_Texture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);
var alphaTex = CutImage(m_Sprite, m_AlphaTexture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);
if (tex.Width != alphaTex.Width || tex.Height != alphaTex.Height)
{
alphaTex.Mutate(x => x.Resize(tex.Width, tex.Height));
}
switch (spriteMaskVisibleMode)
{
case SpriteMaskMode.On:
return ApplyRGBMask(tex, alphaTex);
case SpriteMaskMode.MaskOnly:
tex.Dispose();
return alphaTex;
}
}
else if (m_Sprite.m_RD.texture.TryGet(out m_Texture2D))
{ {
return CutImage(m_Sprite, m_Texture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw); return CutImage(m_Sprite, m_Texture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);
} }
@ -32,6 +58,28 @@ namespace AssetStudio
return null; return null;
} }
private static Image<Bgra32> ApplyRGBMask(Image<Bgra32> tex, Image<Bgra32> texMask)
{
using (texMask)
{
tex.ProcessPixelRows(texMask, (sourceTex, targetTexMask) =>
{
for (int y = 0; y < texMask.Height; y++)
{
var texRow = sourceTex.GetRowSpan(y);
var maskRow = targetTexMask.GetRowSpan(y);
for (int x = 0; x < maskRow.Length; x++)
{
var grayscale = (byte)((maskRow[x].R + maskRow[x].G + maskRow[x].B) / 3);
texRow[x].A = grayscale;
}
}
});
return tex;
}
}
private static Image<Bgra32> CutImage(Sprite m_Sprite, Texture2D m_Texture2D, Rectf textureRect, Vector2 textureRectOffset, float downscaleMultiplier, SpriteSettings settingsRaw) private static Image<Bgra32> CutImage(Sprite m_Sprite, Texture2D m_Texture2D, Rectf textureRect, Vector2 textureRectOffset, float downscaleMultiplier, SpriteSettings settingsRaw)
{ {
var originalImage = m_Texture2D.ConvertToImage(false); var originalImage = m_Texture2D.ConvertToImage(false);