diff --git a/AssetStudioGUI/AssetStudioGUI.csproj b/AssetStudioGUI/AssetStudioGUI.csproj
index 5cc3ac9..95b02bb 100644
--- a/AssetStudioGUI/AssetStudioGUI.csproj
+++ b/AssetStudioGUI/AssetStudioGUI.csproj
@@ -1,83 +1,83 @@
-
- WinExe
- net472;net6.0-windows
- true
- Resources\as.ico
- AssetStudio Mod by VaDiM
- 0.16.47.1
- Copyright © Perfare 2018-2022
- embedded
-
+
+ WinExe
+ net472;net6.0-windows
+ true
+ Resources\as.ico
+ AssetStudio Mod by VaDiM
+ 0.16.47.1
+ Copyright © Perfare 2018-2022
+ embedded
+
-
-
-
-
+
+
+
+
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ True
+ Settings.settings
+
+
-
-
- SettingsSingleFileGenerator
- Settings.Designer.cs
-
-
- True
- Settings.settings
- True
-
-
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+ True
+ Resources.resx
+ True
+
+
-
-
- ResXFileCodeGenerator
- Resources.Designer.cs
-
-
- True
- Resources.resx
- True
-
-
+
+
+ PreserveNewest
+ x86\fmod.dll
+
+
+ PreserveNewest
+ x64\fmod.dll
+
+
-
-
- PreserveNewest
- x86\fmod.dll
-
-
- PreserveNewest
- x64\fmod.dll
-
-
+
+
+
+ Libraries\OpenTK.WinForms.dll
+
+
-
-
-
- Libraries\OpenTK.WinForms.dll
-
-
+
+
+
+
-
-
-
-
+
+
+
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AssetStudioGUI/AssetStudioGUIForm.cs b/AssetStudioGUI/AssetStudioGUIForm.cs
index 8389bf2..0aaa307 100644
--- a/AssetStudioGUI/AssetStudioGUIForm.cs
+++ b/AssetStudioGUI/AssetStudioGUIForm.cs
@@ -43,6 +43,10 @@ namespace AssetStudioGUI
private uint FMODlenms;
private float FMODVolume = 0.8f;
+ #region SpriteControl
+ private SpriteMaskMode spriteMaskVisibleMode = SpriteMaskMode.On;
+ #endregion
+
#region TexControl
private static char[] textureChannelNames = new[] { 'B', 'G', 'R', 'A' };
private bool[] textureChannels = new[] { true, true, true, true };
@@ -315,24 +319,41 @@ namespace AssetStudioGUI
if (e.Control)
{
var need = false;
- switch (e.KeyCode)
+ if (lastSelectedItem.Type == ClassIDType.Texture2D)
{
- case Keys.B:
- textureChannels[0] = !textureChannels[0];
- need = true;
- break;
- case Keys.G:
- textureChannels[1] = !textureChannels[1];
- need = true;
- break;
- case Keys.R:
- textureChannels[2] = !textureChannels[2];
- need = true;
- break;
- case Keys.A:
- textureChannels[3] = !textureChannels[3];
- need = true;
- break;
+ switch (e.KeyCode)
+ {
+ case Keys.B:
+ textureChannels[0] = !textureChannels[0];
+ need = true;
+ break;
+ case Keys.G:
+ textureChannels[1] = !textureChannels[1];
+ need = true;
+ break;
+ case Keys.R:
+ textureChannels[2] = !textureChannels[2];
+ need = true;
+ break;
+ case Keys.A:
+ 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)
{
@@ -1170,13 +1191,19 @@ namespace AssetStudioGUI
private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
{
- var image = m_Sprite.GetImage();
+ var image = m_Sprite.GetImage(spriteMaskVisibleMode);
if (image != null)
{
var bitmap = new DirectBitmap(image.ConvertToBytes(), image.Width, image.Height);
image.Dispose();
assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n";
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
{
diff --git a/AssetStudioGUI/ExportOptions.Designer.cs b/AssetStudioGUI/ExportOptions.Designer.cs
index 1d7f694..943cf49 100644
--- a/AssetStudioGUI/ExportOptions.Designer.cs
+++ b/AssetStudioGUI/ExportOptions.Designer.cs
@@ -32,6 +32,7 @@
this.OKbutton = new System.Windows.Forms.Button();
this.Cancel = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.exportSpriteWithAlphaMask = new System.Windows.Forms.CheckBox();
this.openAfterExport = new System.Windows.Forms.CheckBox();
this.restoreExtensionName = new System.Windows.Forms.CheckBox();
this.assetGroupOptions = new System.Windows.Forms.ComboBox();
@@ -94,6 +95,7 @@
// groupBox1
//
this.groupBox1.AutoSize = true;
+ this.groupBox1.Controls.Add(this.exportSpriteWithAlphaMask);
this.groupBox1.Controls.Add(this.openAfterExport);
this.groupBox1.Controls.Add(this.restoreExtensionName);
this.groupBox1.Controls.Add(this.assetGroupOptions);
@@ -108,12 +110,24 @@
this.groupBox1.TabStop = false;
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
//
this.openAfterExport.AutoSize = true;
this.openAfterExport.Checked = true;
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.Size = new System.Drawing.Size(137, 17);
this.openAfterExport.TabIndex = 10;
@@ -160,7 +174,7 @@
this.convertAudio.AutoSize = true;
this.convertAudio.Checked = true;
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.Size = new System.Drawing.Size(179, 17);
this.convertAudio.TabIndex = 6;
@@ -531,5 +545,6 @@
private System.Windows.Forms.CheckBox openAfterExport;
private System.Windows.Forms.CheckBox exportAllUvsAsDiffuseMaps;
private System.Windows.Forms.ToolTip exportUvsTooltip;
+ private System.Windows.Forms.CheckBox exportSpriteWithAlphaMask;
}
}
\ No newline at end of file
diff --git a/AssetStudioGUI/ExportOptions.cs b/AssetStudioGUI/ExportOptions.cs
index 117ceda..c3542a1 100644
--- a/AssetStudioGUI/ExportOptions.cs
+++ b/AssetStudioGUI/ExportOptions.cs
@@ -12,6 +12,7 @@ namespace AssetStudioGUI
assetGroupOptions.SelectedIndex = Properties.Settings.Default.assetGroupOption;
restoreExtensionName.Checked = Properties.Settings.Default.restoreExtensionName;
converttexture.Checked = Properties.Settings.Default.convertTexture;
+ exportSpriteWithAlphaMask.Checked = Properties.Settings.Default.exportSpriteWithMask;
convertAudio.Checked = Properties.Settings.Default.convertAudio;
var str = Properties.Settings.Default.convertType.ToString();
foreach (Control c in panel1.Controls)
@@ -43,6 +44,7 @@ namespace AssetStudioGUI
Properties.Settings.Default.assetGroupOption = assetGroupOptions.SelectedIndex;
Properties.Settings.Default.restoreExtensionName = restoreExtensionName.Checked;
Properties.Settings.Default.convertTexture = converttexture.Checked;
+ Properties.Settings.Default.exportSpriteWithMask = exportSpriteWithAlphaMask.Checked;
Properties.Settings.Default.convertAudio = convertAudio.Checked;
foreach (Control c in panel1.Controls)
{
@@ -75,6 +77,5 @@ namespace AssetStudioGUI
DialogResult = DialogResult.Cancel;
Close();
}
-
}
}
diff --git a/AssetStudioGUI/ExportOptions.resx b/AssetStudioGUI/ExportOptions.resx
index b60237f..6966b18 100644
--- a/AssetStudioGUI/ExportOptions.resx
+++ b/AssetStudioGUI/ExportOptions.resx
@@ -120,7 +120,4 @@
17, 17
-
- 17, 17
-
\ No newline at end of file
diff --git a/AssetStudioGUI/Exporter.cs b/AssetStudioGUI/Exporter.cs
index 473ce78..41f65ae 100644
--- a/AssetStudioGUI/Exporter.cs
+++ b/AssetStudioGUI/Exporter.cs
@@ -231,9 +231,10 @@ namespace AssetStudioGUI
public static bool ExportSprite(AssetItem item, string exportPath)
{
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))
return false;
- var image = ((Sprite)item.Asset).GetImage();
+ var image = ((Sprite)item.Asset).GetImage(alphaMask);
if (image != null)
{
using (image)
diff --git a/AssetStudioGUI/Properties/Settings.Designer.cs b/AssetStudioGUI/Properties/Settings.Designer.cs
index 2ecec40..bb52046 100644
--- a/AssetStudioGUI/Properties/Settings.Designer.cs
+++ b/AssetStudioGUI/Properties/Settings.Designer.cs
@@ -1,10 +1,10 @@
//------------------------------------------------------------------------------
//
-// 此代码由工具生成。
-// 运行时版本:4.0.30319.42000
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
//
-// 对此文件的更改可能会导致不正确的行为,并且如果
-// 重新生成代码,这些更改将会丢失。
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
//
//------------------------------------------------------------------------------
@@ -12,7 +12,7 @@ namespace AssetStudioGUI.Properties {
[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 {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -274,5 +274,17 @@ namespace AssetStudioGUI.Properties {
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;
+ }
+ }
}
}
diff --git a/AssetStudioGUI/Properties/Settings.settings b/AssetStudioGUI/Properties/Settings.settings
index d6eb751..aef06e0 100644
--- a/AssetStudioGUI/Properties/Settings.settings
+++ b/AssetStudioGUI/Properties/Settings.settings
@@ -65,5 +65,8 @@
False
+
+ True
+
\ No newline at end of file
diff --git a/AssetStudioUtility/SpriteHelper.cs b/AssetStudioUtility/SpriteHelper.cs
index 56f17a3..5c6a356 100644
--- a/AssetStudioUtility/SpriteHelper.cs
+++ b/AssetStudioUtility/SpriteHelper.cs
@@ -11,9 +11,16 @@ using System.Numerics;
namespace AssetStudio
{
+ public enum SpriteMaskMode
+ {
+ Off,
+ On,
+ MaskOnly
+ }
+
public static class SpriteHelper
{
- public static Image GetImage(this Sprite m_Sprite)
+ public static Image GetImage(this Sprite m_Sprite, SpriteMaskMode spriteMaskVisibleMode = SpriteMaskMode.On)
{
if (m_Sprite.m_SpriteAtlas != null && m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlas))
{
@@ -24,7 +31,26 @@ namespace AssetStudio
}
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);
}
@@ -32,6 +58,28 @@ namespace AssetStudio
return null;
}
+ private static Image ApplyRGBMask(Image tex, Image 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 CutImage(Sprite m_Sprite, Texture2D m_Texture2D, Rectf textureRect, Vector2 textureRectOffset, float downscaleMultiplier, SpriteSettings settingsRaw)
{
var originalImage = m_Texture2D.ConvertToImage(false);