diff --git a/AssetStudio/Classes/Sprite.cs b/AssetStudio/Classes/Sprite.cs index 752794f..034c02b 100644 --- a/AssetStudio/Classes/Sprite.cs +++ b/AssetStudio/Classes/Sprite.cs @@ -205,6 +205,7 @@ namespace AssetStudio public PPtr m_SpriteAtlas; public SpriteRenderData m_RD; public Vector2[][] m_PhysicsShape; + public bool akSplitAlpha; public Sprite(ObjectReader reader) : base(reader) { @@ -254,6 +255,8 @@ namespace AssetStudio } } + akSplitAlpha = false; + //vector m_Bones 2018 and up } } diff --git a/AssetStudioGUI/AssetStudioGUIForm.Designer.cs b/AssetStudioGUI/AssetStudioGUIForm.Designer.cs index 0752b33..7c339d3 100644 --- a/AssetStudioGUI/AssetStudioGUIForm.Designer.cs +++ b/AssetStudioGUI/AssetStudioGUIForm.Designer.cs @@ -41,6 +41,11 @@ this.displayAll = new System.Windows.Forms.ToolStripMenuItem(); this.enablePreview = new System.Windows.Forms.ToolStripMenuItem(); this.displayInfo = new System.Windows.Forms.ToolStripMenuItem(); + this.akSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.akTitleMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.akFixFaceSpriteNamesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.akUseExternalAlphaToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.akSeparator2 = new System.Windows.Forms.ToolStripSeparator(); this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem(); this.specifyUnityVersion = new System.Windows.Forms.ToolStripTextBox(); this.showExpOpt = new System.Windows.Forms.ToolStripMenuItem(); @@ -231,6 +236,11 @@ this.displayAll, this.enablePreview, this.displayInfo, + this.akSeparator1, + this.akTitleMenuItem, + this.akFixFaceSpriteNamesToolStripMenuItem, + this.akUseExternalAlphaToolStripMenuItem, + this.akSeparator2, this.toolStripMenuItem14, this.showExpOpt}); this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem"; @@ -241,7 +251,7 @@ // this.displayAll.CheckOnClick = true; this.displayAll.Name = "displayAll"; - this.displayAll.Size = new System.Drawing.Size(207, 22); + this.displayAll.Size = new System.Drawing.Size(265, 22); this.displayAll.Text = "Display all assets"; this.displayAll.ToolTipText = "Check this option will display all types assets. Not extractable assets can expor" + "t the RAW file."; @@ -253,7 +263,7 @@ this.enablePreview.CheckOnClick = true; this.enablePreview.CheckState = System.Windows.Forms.CheckState.Checked; this.enablePreview.Name = "enablePreview"; - this.enablePreview.Size = new System.Drawing.Size(207, 22); + this.enablePreview.Size = new System.Drawing.Size(265, 22); this.enablePreview.Text = "Enable preview"; this.enablePreview.ToolTipText = "Toggle the loading and preview of readable assets, such as images, sounds, text, " + "etc.\r\nDisable preview if you have performance or compatibility issues."; @@ -265,18 +275,60 @@ this.displayInfo.CheckOnClick = true; this.displayInfo.CheckState = System.Windows.Forms.CheckState.Checked; this.displayInfo.Name = "displayInfo"; - this.displayInfo.Size = new System.Drawing.Size(207, 22); + this.displayInfo.Size = new System.Drawing.Size(265, 22); this.displayInfo.Text = "Display asset information"; this.displayInfo.ToolTipText = "Toggle the overlay that shows information about each asset, eg. image size, forma" + "t, audio bitrate, etc."; this.displayInfo.CheckedChanged += new System.EventHandler(this.displayAssetInfo_Check); // + // akSeparator1 + // + this.akSeparator1.Name = "akSeparator1"; + this.akSeparator1.Size = new System.Drawing.Size(262, 6); + // + // akTitleMenuItem + // + this.akTitleMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.akTitleMenuItem.Enabled = false; + this.akTitleMenuItem.Name = "akTitleMenuItem"; + this.akTitleMenuItem.ShowShortcutKeys = false; + this.akTitleMenuItem.Size = new System.Drawing.Size(265, 22); + this.akTitleMenuItem.Text = "Arknighs"; + // + // akFixFaceSpriteNamesToolStripMenuItem + // + this.akFixFaceSpriteNamesToolStripMenuItem.Checked = true; + this.akFixFaceSpriteNamesToolStripMenuItem.CheckOnClick = true; + this.akFixFaceSpriteNamesToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; + this.akFixFaceSpriteNamesToolStripMenuItem.Name = "akFixFaceSpriteNamesToolStripMenuItem"; + this.akFixFaceSpriteNamesToolStripMenuItem.Size = new System.Drawing.Size(265, 22); + this.akFixFaceSpriteNamesToolStripMenuItem.Text = "Fix names of avg face sprites"; + this.akFixFaceSpriteNamesToolStripMenuItem.ToolTipText = "Rename face sprites with numeric names to correct ones"; + this.akFixFaceSpriteNamesToolStripMenuItem.CheckedChanged += new System.EventHandler(this.akFixFaceSpriteNamesToolStripMenuItem_Check); + // + // akUseExternalAlphaToolStripMenuItem + // + this.akUseExternalAlphaToolStripMenuItem.Checked = true; + this.akUseExternalAlphaToolStripMenuItem.CheckOnClick = true; + this.akUseExternalAlphaToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; + this.akUseExternalAlphaToolStripMenuItem.Name = "akUseExternalAlphaToolStripMenuItem"; + this.akUseExternalAlphaToolStripMenuItem.Size = new System.Drawing.Size(265, 22); + this.akUseExternalAlphaToolStripMenuItem.Text = "Use external alpha texture for sprites"; + this.akUseExternalAlphaToolStripMenuItem.ToolTipText = "Trying to find an external alpha texture for preview/export sprite assets (Skins," + + " Char arts, Avg char arts, etc.)"; + this.akUseExternalAlphaToolStripMenuItem.CheckedChanged += new System.EventHandler(this.akUseExternalAlphaToolStripMenuItem_Check); + // + // akSeparator2 + // + this.akSeparator2.Name = "akSeparator2"; + this.akSeparator2.Size = new System.Drawing.Size(262, 6); + // // toolStripMenuItem14 // this.toolStripMenuItem14.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.specifyUnityVersion}); this.toolStripMenuItem14.Name = "toolStripMenuItem14"; - this.toolStripMenuItem14.Size = new System.Drawing.Size(207, 22); + this.toolStripMenuItem14.Size = new System.Drawing.Size(265, 22); this.toolStripMenuItem14.Text = "Specify Unity version"; // // specifyUnityVersion @@ -290,7 +342,7 @@ // showExpOpt // this.showExpOpt.Name = "showExpOpt"; - this.showExpOpt.Size = new System.Drawing.Size(207, 22); + this.showExpOpt.Size = new System.Drawing.Size(265, 22); this.showExpOpt.Text = "Export options"; this.showExpOpt.Click += new System.EventHandler(this.showExpOpt_Click); // @@ -1405,6 +1457,11 @@ private System.Windows.Forms.ToolStripMenuItem showRelatedAssetsToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator7; private System.Windows.Forms.ListView assetListView; + private System.Windows.Forms.ToolStripMenuItem akFixFaceSpriteNamesToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem akUseExternalAlphaToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator akSeparator1; + private System.Windows.Forms.ToolStripMenuItem akTitleMenuItem; + private System.Windows.Forms.ToolStripSeparator akSeparator2; } } diff --git a/AssetStudioGUI/AssetStudioGUIForm.cs b/AssetStudioGUI/AssetStudioGUIForm.cs index 55db635..13f7a9c 100644 --- a/AssetStudioGUI/AssetStudioGUIForm.cs +++ b/AssetStudioGUI/AssetStudioGUIForm.cs @@ -1,4 +1,5 @@ -using AssetStudio; +using Arknights; +using AssetStudio; using Newtonsoft.Json; using OpenTK; using OpenTK.Graphics.OpenGL; @@ -19,6 +20,8 @@ using System.Timers; using System.Windows.Forms; using static AssetStudioGUI.Studio; using Font = AssetStudio.Font; +using SharpImage = SixLabors.ImageSharp; +using SharpImageFormat = SixLabors.ImageSharp.PixelFormats; using Microsoft.WindowsAPICodePack.Taskbar; #if NET472 using Vector3 = OpenTK.Vector3; @@ -47,6 +50,7 @@ namespace AssetStudioGUI #region SpriteControl private SpriteMaskMode spriteMaskVisibleMode = SpriteMaskMode.On; + private bool showDebugInfo = false; #endregion #region TexControl @@ -122,6 +126,8 @@ namespace AssetStudioGUI displayAll.Checked = Properties.Settings.Default.displayAll; displayInfo.Checked = Properties.Settings.Default.displayInfo; enablePreview.Checked = Properties.Settings.Default.enablePreview; + akFixFaceSpriteNamesToolStripMenuItem.Checked = Properties.Settings.Default.fixFaceSpriteNames; + akUseExternalAlphaToolStripMenuItem.Checked = Properties.Settings.Default.useExternalAlpha; FMODinit(); listSearchFilterMode.SelectedIndex = 0; @@ -252,6 +258,9 @@ namespace AssetStudioGUI typeMap.Clear(); classesListView.EndUpdate(); + if (akFixFaceSpriteNamesToolStripMenuItem.Checked) + FixFaceSpriteNames(); + var types = exportableAssets.Select(x => x.Type).Distinct().OrderBy(x => x.ToString()).ToArray(); foreach (var type in types) { @@ -363,6 +372,10 @@ namespace AssetStudioGUI spriteMaskVisibleMode = spriteMaskVisibleMode == SpriteMaskMode.MaskOnly ? SpriteMaskMode.On : SpriteMaskMode.MaskOnly; need = true; break; + case Keys.D: + showDebugInfo = !showDebugInfo; + need = true; + break; } } if (need) @@ -1262,7 +1275,33 @@ namespace AssetStudioGUI private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite) { - var image = m_Sprite.GetImage(spriteMaskMode: spriteMaskVisibleMode); + SharpImage.Image image; + AvgSprite avgSprite = null; + + bool isCharAvgSprite = assetItem.Container.Contains("avg/characters"); + bool isCharArt = assetItem.Container.Contains("arts/characters"); + if (isCharAvgSprite) + { + avgSprite = new AvgSprite(assetItem); + } + if (akUseExternalAlphaToolStripMenuItem.Checked && (isCharAvgSprite || isCharArt)) + { + if (m_Sprite.m_RD.alphaTexture.IsNull) + { + var charAlphaTex = AkSpriteHelper.TryFindAlphaTex(assetItem, avgSprite, isCharAvgSprite); + if (charAlphaTex != null) + { + m_Sprite.m_RD.alphaTexture.Set(charAlphaTex); + m_Sprite.akSplitAlpha = true; + } + } + image = m_Sprite.AkGetImage(avgSprite, spriteMaskMode: spriteMaskVisibleMode); + } + else + { + image = m_Sprite.GetImage(spriteMaskMode: spriteMaskVisibleMode); + } + if (image != null) { var bitmap = new DirectBitmap(image); @@ -1270,10 +1309,33 @@ namespace AssetStudioGUI assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n"; PreviewTexture(bitmap); - if (!m_Sprite.m_RD.alphaTexture.IsNull) + if (!m_Sprite.m_RD.alphaTexture.IsNull && (akUseExternalAlphaToolStripMenuItem.Checked || !m_Sprite.akSplitAlpha)) { - assetItem.InfoText += $"Alpha Mask: {spriteMaskVisibleMode}\n"; - StatusStripUpdate("'Ctrl'+'A' - Enable/Disable alpha mask usage. 'Ctrl'+'M' - Show alpha mask only."); + var sb = new StringBuilder(); + + sb.AppendLine($"Alpha mask: {spriteMaskVisibleMode}"); + sb.Append(spriteMaskVisibleMode != SpriteMaskMode.Off ? $"Is external mask: {m_Sprite.akSplitAlpha}\n" : ""); + if (avgSprite != null) + { + sb.AppendLine($"Alias: \"{avgSprite.Alias}\""); + if (showDebugInfo) + { + sb.AppendLine($"[Debug]"); + sb.AppendLine($"Is avg hub parsed: {avgSprite.IsHubParsed}"); + if (avgSprite.IsHubParsed) + { + sb.AppendLine($"Is face data exist: {avgSprite.FaceSize.Width > 0}"); + sb.AppendLine($"Is face sprite: {avgSprite.IsFaceSprite}"); + sb.AppendLine($"Is whole body sprite: {avgSprite.IsWholeBodySprite}"); + } + } + StatusStripUpdate("'Ctrl'+'A' - Enable/Disable alpha mask usage. 'Ctrl'+'M' - Show alpha mask only. 'Ctrl'+'D' - Show debug info."); + } + else + { + StatusStripUpdate("'Ctrl'+'A' - Enable/Disable alpha mask usage. 'Ctrl'+'M' - Show alpha mask only."); + } + assetItem.InfoText += sb.ToString(); } } else @@ -1379,6 +1441,33 @@ namespace AssetStudioGUI FMODreset(); } + private void FixFaceSpriteNames() + { + assetListView.BeginUpdate(); + for (int i = 0; i < assetListView.Items.Count; i++) + { + var assetItem = (AssetItem)assetListView.Items[i]; + if (assetItem.Type == ClassIDType.Sprite) + { + var sprite = (Sprite)assetItem.Asset; + if (akFixFaceSpriteNamesToolStripMenuItem.Checked) + { + if ((sprite.m_Name.Length < 3 && sprite.m_Name.All(char.IsDigit)) //not grouped ("spriteIndex") + || (sprite.m_Name.Length < 5 && sprite.m_Name.Contains('$') && sprite.m_Name.Split('$')[0].All(char.IsDigit))) //grouped ("spriteIndex$groupIndex") + { + var fullName = Path.GetFileNameWithoutExtension(assetItem.Container); + assetItem.Text = $"{fullName}#{sprite.m_Name}"; + } + } + else if (assetItem.Text != sprite.m_Name) + { + assetItem.Text = sprite.m_Name; + } + } + } + assetListView.EndUpdate(); + } + private void tabControl2_SelectedIndexChanged(object sender, EventArgs e) { if (tabControl2.SelectedIndex == 1 && lastSelectedItem != null) @@ -1867,6 +1956,26 @@ namespace AssetStudioGUI sceneTreeView.EndUpdate(); } + private void akFixFaceSpriteNamesToolStripMenuItem_Check(object sender, EventArgs e) + { + Properties.Settings.Default.fixFaceSpriteNames = akFixFaceSpriteNamesToolStripMenuItem.Checked; + Properties.Settings.Default.Save(); + FixFaceSpriteNames(); + } + + private void akUseExternalAlphaToolStripMenuItem_Check(object sender, EventArgs e) + { + Properties.Settings.Default.useExternalAlpha = akUseExternalAlphaToolStripMenuItem.Checked; + Properties.Settings.Default.Save(); + + if (lastSelectedItem?.Asset.type == ClassIDType.Sprite) + { + StatusStripUpdate(""); + PreviewAsset(lastSelectedItem); + assetInfoLabel.Text = lastSelectedItem.InfoText; + } + } + private void aboutToolStripMenuItem_Click(object sender, EventArgs e) { var aboutForm = new AboutForm(); diff --git a/AssetStudioGUI/Components/Arknights/AkSpriteHelper.cs b/AssetStudioGUI/Components/Arknights/AkSpriteHelper.cs new file mode 100644 index 0000000..8d00b81 --- /dev/null +++ b/AssetStudioGUI/Components/Arknights/AkSpriteHelper.cs @@ -0,0 +1,200 @@ +using AssetStudio; +using AssetStudioGUI; +using AssetStudioGUI.Properties; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Transforms; +using System; +using System.IO; + +namespace Arknights +{ + internal static class AkSpriteHelper + { + public static Texture2D TryFindAlphaTex(AssetItem assetItem, AvgSprite avgSprite, bool isAvgSprite) + { + Sprite m_Sprite = (Sprite)assetItem.Asset; + var imgType = "arts/characters"; + if (m_Sprite.m_RD.alphaTexture.m_PathID == 0) + { + if (isAvgSprite) + { + if (avgSprite?.FullAlphaTexture != null) + return avgSprite.FullAlphaTexture; + + imgType = "avg/characters"; //since the avg hub was not found for some reason, let's try to find alpha tex by name + } + var spriteFullName = Path.GetFileNameWithoutExtension(assetItem.Container); + foreach (var item in Studio.exportableAssets) + { + if (item.Type == ClassIDType.Texture2D) + { + if (item.Container.Contains(imgType) && item.Container.Contains($"illust_{m_Sprite.m_Name}_material") && item.Text.Contains("[alpha]")) + return (Texture2D)item.Asset; + else if (item.Container.Contains(imgType) && item.Container.Contains(spriteFullName) && item.Text == $"{m_Sprite.m_Name}[alpha]") + return (Texture2D)item.Asset; + } + } + } + return null; + } + + public static Image AkGetImage(this Sprite m_Sprite, AvgSprite avgSprite = null, SpriteMaskMode spriteMaskMode = SpriteMaskMode.On) + { + if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D) && m_Sprite.m_RD.alphaTexture.TryGet(out var m_AlphaTexture2D) && spriteMaskMode != SpriteMaskMode.Off) + { + Image tex; + Image alphaTex; + + if (avgSprite != null && avgSprite.IsHubParsed) + { + alphaTex = m_AlphaTexture2D.ConvertToImage(true); + if (avgSprite.IsFaceSprite) + { + var faceImage = m_Texture2D.ConvertToImage(true); + var faceAlpha = avgSprite.FaceSpriteAlphaTexture.ConvertToImage(true); + if (faceImage.Size() != avgSprite.FaceSize) + { + faceImage.Mutate(x => x.Resize(new ResizeOptions { Size = avgSprite.FaceSize, Sampler = KnownResamplers.Lanczos3, Mode = ResizeMode.Stretch })); + faceAlpha.Mutate(x => x.Resize(new ResizeOptions { Size = avgSprite.FaceSize, Sampler = KnownResamplers.Lanczos3, Mode = ResizeMode.Stretch })); + } + tex = avgSprite.FullTexture.ConvertToImage(true); + tex.Mutate(x => x.DrawImage(faceImage, location: avgSprite.FacePos, opacity: 1f)); + alphaTex.Mutate(x => x.DrawImage(faceAlpha, location: avgSprite.FacePos, opacity: 1f)); + } + else + { + tex = m_Texture2D.ConvertToImage(true); + } + } + else + { + tex = CutImage(m_Texture2D.ConvertToImage(false), m_Sprite.m_RD.textureRect, m_Sprite.m_RD.downscaleMultiplier); + alphaTex = CutImage(m_AlphaTexture2D.ConvertToImage(false), m_Sprite.m_RD.textureRect, m_Sprite.m_RD.downscaleMultiplier); + } + + switch (spriteMaskMode) + { + case SpriteMaskMode.On: + tex.ApplyRGBMask(alphaTex, isPreview: true); + return tex; + case SpriteMaskMode.Export: + tex.ApplyRGBMask(alphaTex); + return tex; + case SpriteMaskMode.MaskOnly: + tex.Dispose(); + return alphaTex; + } + } + else if (m_Sprite.m_RD.texture.TryGet(out m_Texture2D)) + { + return CutImage(m_Texture2D.ConvertToImage(false), m_Sprite.m_RD.textureRect, m_Sprite.m_RD.downscaleMultiplier); + } + + return null; + } + + private static IResampler GetResampler(bool isPreview) + { + IResampler resampler; + if (isPreview) + { + resampler = KnownResamplers.NearestNeighbor; + } + else + { + switch (Settings.Default.resamplerIndex) + { + case 0: + resampler = KnownResamplers.NearestNeighbor; + break; + case 1: //Bilinear + resampler = KnownResamplers.Triangle; + break; + case 2: + resampler = KnownResamplers.Bicubic; + break; + case 3: + resampler = KnownResamplers.MitchellNetravali; + break; + case 4: + resampler = KnownResamplers.Spline; + break; + case 5: + resampler = KnownResamplers.Welch; + break; + default: + resampler = KnownResamplers.MitchellNetravali; + break; + } + } + return resampler; + } + + private static void ApplyRGBMask(this Image tex, Image texMask, bool isPreview = false) + { + using (texMask) + { + bool resized = false; + if (tex.Width != texMask.Width || tex.Height != texMask.Height) + { + texMask.Mutate(x => x.Resize(tex.Width, tex.Height, GetResampler(isPreview))); + resized = true; + } + + var invGamma = 1.0 / (1.0 + Settings.Default.alphaMaskGamma / 10.0); + if (Settings.Default.resizedOnly && !resized) + { + invGamma = 1.0; + } + + 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 = (maskRow[x].R + maskRow[x].G + maskRow[x].B) / 3.0; + if (invGamma != 1) + { + grayscale = 255 - Math.Pow((255 - grayscale) / 255, invGamma) * 255; + } + texRow[x].A = (byte)grayscale; + } + } + }); + } + } + + private static Image CutImage(Image originalImage, Rectf textureRect, float downscaleMultiplier) + { + if (originalImage != null) + { + using (originalImage) + { + if (downscaleMultiplier > 0f && downscaleMultiplier != 1f) + { + var newSize = (Size)(originalImage.Size() / downscaleMultiplier); + originalImage.Mutate(x => x.Resize(newSize, KnownResamplers.Lanczos3, compand: true)); + } + var rectX = (int)Math.Floor(textureRect.x); + var rectY = (int)Math.Floor(textureRect.y); + var rectRight = (int)Math.Ceiling(textureRect.x + textureRect.width); + var rectBottom = (int)Math.Ceiling(textureRect.y + textureRect.height); + rectRight = Math.Min(rectRight, originalImage.Width); + rectBottom = Math.Min(rectBottom, originalImage.Height); + var rect = new Rectangle(rectX, rectY, rectRight - rectX, rectBottom - rectY); + var spriteImage = originalImage.Clone(x => x.Crop(rect)); + spriteImage.Mutate(x => x.Flip(FlipMode.Vertical)); + + return spriteImage; + } + } + + return null; + } + } +} diff --git a/AssetStudioGUI/Components/Arknights/AvgSprite.cs b/AssetStudioGUI/Components/Arknights/AvgSprite.cs new file mode 100644 index 0000000..44d046a --- /dev/null +++ b/AssetStudioGUI/Components/Arknights/AvgSprite.cs @@ -0,0 +1,125 @@ +using Arknights.AvgCharHub; +using AssetStudio; +using AssetStudioGUI; +using SixLabors.ImageSharp; +using System.Linq; +using System; +using Newtonsoft.Json; + +namespace Arknights +{ + internal class AvgSprite + { + public Texture2D FaceSpriteAlphaTexture { get; } + public Texture2D FullTexture { get; } + public Texture2D FullAlphaTexture { get; } + public Point FacePos { get; } + public Size FaceSize { get; } + public string Alias { get; } + public bool IsWholeBodySprite { get; } + public bool IsFaceSprite { get; } + public bool IsHubParsed { get; } + + private AvgSpriteConfig GetCurSpriteGroup(AvgSpriteConfigGroup spriteHubDataGrouped, long spriteItemID, string spriteName) + { + if (spriteHubDataGrouped.SpriteGroups.Length > 1) + { + if (!string.IsNullOrEmpty(spriteName)) + { + var groupFromName = int.TryParse(spriteName?.Substring(spriteName.IndexOf('$') + 1, 1), out int groupIndex); + if (groupFromName) + { + return spriteHubDataGrouped.SpriteGroups[groupIndex - 1]; + } + } + return spriteHubDataGrouped.SpriteGroups.FirstOrDefault(x => x.Sprites.Any(y => y.Sprite.m_PathID == spriteItemID)); + } + else + { + return spriteHubDataGrouped.SpriteGroups[0]; + } + } + + private bool TryGetSpriteHub(AssetItem assetItem, out AvgSpriteConfig spriteHubData) + { + spriteHubData = null; + var avgSpriteHubItem = Studio.exportableAssets.Find(x => + x.Type == ClassIDType.MonoBehaviour + && x.Container == assetItem.Container + && x.Text.IndexOf("AVGCharacterSpriteHub", StringComparison.OrdinalIgnoreCase) >= 0 + ); + if (avgSpriteHubItem == null) + { + Logger.Warning("AVGCharacterSpriteHub was not found."); + return false; + } + var spriteHubDict = ((MonoBehaviour)avgSpriteHubItem.Asset).ToType(); + if (spriteHubDict == null) + { + Logger.Warning("AVGCharacterSpriteHub is not readable."); + return false; + } + + var spriteHubJson = JsonConvert.SerializeObject(spriteHubDict); + if (avgSpriteHubItem.Text.ToLower().Contains("hubgroup")) + { + var groupedSpriteHub = JsonConvert.DeserializeObject(spriteHubJson); + spriteHubData = GetCurSpriteGroup(groupedSpriteHub, assetItem.m_PathID, assetItem.Text); + } + else + { + spriteHubData = JsonConvert.DeserializeObject(spriteHubJson); + } + + return true; + } + + public AvgSprite(AssetItem assetItem) + { + if (TryGetSpriteHub(assetItem, out var spriteHubData)) + { + IsHubParsed = spriteHubData?.Sprites.Length > 0; + } + if (IsHubParsed) + { + var curSpriteData = spriteHubData.Sprites.FirstOrDefault(x => x.Sprite.m_PathID == assetItem.m_PathID); + + if (curSpriteData == null) + { + Studio.StatusStripUpdate($"Sprite \"{assetItem.Text}\" was not found in the avg sprite hub."); + return; + } + + Alias = curSpriteData.Alias; + IsWholeBodySprite = curSpriteData.IsWholeBody; + + if (spriteHubData.FaceSize.X > 0 && spriteHubData.FaceSize.Y > 0) + { + var fullTexSpriteData = spriteHubData.Sprites.Last(); //Last sprite item in the list usually contains PathID of Sprite with full texture + if (IsWholeBodySprite || curSpriteData.Equals(fullTexSpriteData)) + { + fullTexSpriteData = curSpriteData; + } + else + { + var faceAlphaID = curSpriteData.AlphaTex.m_PathID; + FaceSpriteAlphaTexture = (Texture2D)Studio.exportableAssets.Find(x => x.m_PathID == faceAlphaID).Asset; + } + var fullTexSpriteID = fullTexSpriteData.Sprite.m_PathID; + var fullTexAlphaID = fullTexSpriteData.AlphaTex.m_PathID; + var fullTexSprite = (Sprite)Studio.exportableAssets.Find(x => x.m_PathID == fullTexSpriteID).Asset; + + FullTexture = fullTexSprite.m_RD.texture.TryGet(out var fullTex) ? fullTex : null; + FullAlphaTexture = (Texture2D)Studio.exportableAssets.Find(x => x.m_PathID == fullTexAlphaID).Asset; + FacePos = new Point((int)Math.Round(spriteHubData.FacePos.X), (int)Math.Round(spriteHubData.FacePos.Y)); + FaceSize = new Size((int)Math.Round(spriteHubData.FaceSize.X), (int)Math.Round(spriteHubData.FaceSize.Y)); + IsFaceSprite = assetItem.m_PathID != fullTexSpriteID; + } + else + { + FullAlphaTexture = (Texture2D)Studio.exportableAssets.Find(x => x.m_PathID == curSpriteData.AlphaTex.m_PathID).Asset; + } + } + } + } +} diff --git a/AssetStudioGUI/Components/Arknights/AvgSpriteConfig.cs b/AssetStudioGUI/Components/Arknights/AvgSpriteConfig.cs new file mode 100644 index 0000000..d834743 --- /dev/null +++ b/AssetStudioGUI/Components/Arknights/AvgSpriteConfig.cs @@ -0,0 +1,30 @@ +using AssetStudio; + +namespace Arknights.AvgCharHub +{ + internal class AvgAssetIDs + { + public int m_FileID { get; set; } + public long m_PathID { get; set; } + } + + internal class AvgSpriteData + { + public AvgAssetIDs Sprite { get; set; } + public AvgAssetIDs AlphaTex { get; set; } + public string Alias { get; set; } + public bool IsWholeBody { get; set; } + } + + internal class AvgSpriteConfig + { + public AvgSpriteData[] Sprites { get; set; } + public Vector2 FaceSize { get; set; } + public Vector3 FacePos { get; set; } + } + + internal class AvgSpriteConfigGroup + { + public AvgSpriteConfig[] SpriteGroups { get; set; } + } +} diff --git a/AssetStudioGUI/ExportOptions.Designer.cs b/AssetStudioGUI/ExportOptions.Designer.cs index a99aa21..b068685 100644 --- a/AssetStudioGUI/ExportOptions.Designer.cs +++ b/AssetStudioGUI/ExportOptions.Designer.cs @@ -64,17 +64,31 @@ this.exportAllNodes = new System.Windows.Forms.CheckBox(); this.eulerFilter = new System.Windows.Forms.CheckBox(); this.exportUvsTooltip = new System.Windows.Forms.ToolTip(this.components); + this.akResamplerLabel = new System.Windows.Forms.Label(); + this.akResamplerComboBox = new System.Windows.Forms.ComboBox(); + this.akSpritesAlphaGroupBox = new System.Windows.Forms.GroupBox(); + this.akGammaNoteLabel = new System.Windows.Forms.Label(); + this.akResamplerDescLabel = new System.Windows.Forms.Label(); + this.akResizedOnlyCheckBox = new System.Windows.Forms.CheckBox(); + this.akGammaValueLabel = new System.Windows.Forms.Label(); + this.akGammaLabel = new System.Windows.Forms.Label(); + this.akAlphaMaskGammaTrackBar = new System.Windows.Forms.TrackBar(); + this.akSpritesExportGroupBox = new System.Windows.Forms.GroupBox(); + this.akAddAliasesCheckBox = new System.Windows.Forms.CheckBox(); this.groupBox1.SuspendLayout(); this.panel1.SuspendLayout(); this.groupBox2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.scaleFactor)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.boneSize)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.filterPrecision)).BeginInit(); + this.akSpritesAlphaGroupBox.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.akAlphaMaskGammaTrackBar)).BeginInit(); + this.akSpritesExportGroupBox.SuspendLayout(); this.SuspendLayout(); // // OKbutton // - this.OKbutton.Location = new System.Drawing.Point(381, 380); + this.OKbutton.Location = new System.Drawing.Point(681, 381); this.OKbutton.Name = "OKbutton"; this.OKbutton.Size = new System.Drawing.Size(75, 23); this.OKbutton.TabIndex = 6; @@ -85,7 +99,7 @@ // Cancel // this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.Cancel.Location = new System.Drawing.Point(462, 380); + this.Cancel.Location = new System.Drawing.Point(762, 381); this.Cancel.Name = "Cancel"; this.Cancel.Size = new System.Drawing.Size(75, 23); this.Cancel.TabIndex = 7; @@ -493,13 +507,140 @@ this.eulerFilter.Text = "EulerFilter"; this.eulerFilter.UseVisualStyleBackColor = true; // + // akResamplerLabel + // + this.akResamplerLabel.AutoSize = true; + this.akResamplerLabel.Location = new System.Drawing.Point(6, 21); + this.akResamplerLabel.Name = "akResamplerLabel"; + this.akResamplerLabel.Size = new System.Drawing.Size(113, 13); + this.akResamplerLabel.TabIndex = 5; + this.akResamplerLabel.Text = "Alpha mask resampler:"; + this.exportUvsTooltip.SetToolTip(this.akResamplerLabel, "Only affects exported images"); + // + // akResamplerComboBox + // + this.akResamplerComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.akResamplerComboBox.FormattingEnabled = true; + this.akResamplerComboBox.Items.AddRange(new object[] { + "Nearest Neighbor", + "Bilinear", + "Bicubic", + "Mitchell-Netravali", + "Spline", + "Welch"}); + this.akResamplerComboBox.Location = new System.Drawing.Point(125, 18); + this.akResamplerComboBox.Name = "akResamplerComboBox"; + this.akResamplerComboBox.Size = new System.Drawing.Size(169, 21); + this.akResamplerComboBox.TabIndex = 4; + this.exportUvsTooltip.SetToolTip(this.akResamplerComboBox, "Only affects exported images"); + // + // akSpritesAlphaGroupBox + // + this.akSpritesAlphaGroupBox.Controls.Add(this.akGammaNoteLabel); + this.akSpritesAlphaGroupBox.Controls.Add(this.akResamplerDescLabel); + this.akSpritesAlphaGroupBox.Controls.Add(this.akResamplerLabel); + this.akSpritesAlphaGroupBox.Controls.Add(this.akResamplerComboBox); + this.akSpritesAlphaGroupBox.Controls.Add(this.akResizedOnlyCheckBox); + this.akSpritesAlphaGroupBox.Controls.Add(this.akGammaValueLabel); + this.akSpritesAlphaGroupBox.Controls.Add(this.akGammaLabel); + this.akSpritesAlphaGroupBox.Controls.Add(this.akAlphaMaskGammaTrackBar); + this.akSpritesAlphaGroupBox.Location = new System.Drawing.Point(537, 13); + this.akSpritesAlphaGroupBox.Name = "akSpritesAlphaGroupBox"; + this.akSpritesAlphaGroupBox.Size = new System.Drawing.Size(300, 178); + this.akSpritesAlphaGroupBox.TabIndex = 12; + this.akSpritesAlphaGroupBox.TabStop = false; + this.akSpritesAlphaGroupBox.Text = "Sprites: Alpha Mask [Arknights]"; + // + // akGammaNoteLabel + // + this.akGammaNoteLabel.AutoSize = true; + this.akGammaNoteLabel.ForeColor = System.Drawing.SystemColors.GrayText; + this.akGammaNoteLabel.Location = new System.Drawing.Point(6, 138); + this.akGammaNoteLabel.Name = "akGammaNoteLabel"; + this.akGammaNoteLabel.Size = new System.Drawing.Size(230, 13); + this.akGammaNoteLabel.TabIndex = 7; + this.akGammaNoteLabel.Text = "* Gamma settings also affect the preview image"; + // + // akResamplerDescLabel + // + this.akResamplerDescLabel.AutoSize = true; + this.akResamplerDescLabel.ForeColor = System.Drawing.SystemColors.GrayText; + this.akResamplerDescLabel.Location = new System.Drawing.Point(6, 43); + this.akResamplerDescLabel.Name = "akResamplerDescLabel"; + this.akResamplerDescLabel.Size = new System.Drawing.Size(244, 13); + this.akResamplerDescLabel.TabIndex = 6; + this.akResamplerDescLabel.Text = "Alpha mask upscale method for 2048x2048 sprites"; + // + // akResizedOnlyCheckBox + // + this.akResizedOnlyCheckBox.AutoSize = true; + this.akResizedOnlyCheckBox.Checked = true; + this.akResizedOnlyCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; + this.akResizedOnlyCheckBox.Location = new System.Drawing.Point(172, 85); + this.akResizedOnlyCheckBox.Name = "akResizedOnlyCheckBox"; + this.akResizedOnlyCheckBox.Size = new System.Drawing.Size(122, 17); + this.akResizedOnlyCheckBox.TabIndex = 3; + this.akResizedOnlyCheckBox.Text = "Apply to resized only"; + this.akResizedOnlyCheckBox.UseVisualStyleBackColor = true; + // + // akGammaValueLabel + // + this.akGammaValueLabel.AutoSize = true; + this.akGammaValueLabel.Location = new System.Drawing.Point(111, 86); + this.akGammaValueLabel.Name = "akGammaValueLabel"; + this.akGammaValueLabel.Size = new System.Drawing.Size(41, 13); + this.akGammaValueLabel.TabIndex = 2; + this.akGammaValueLabel.Text = "Default"; + // + // akGammaLabel + // + this.akGammaLabel.AutoSize = true; + this.akGammaLabel.Location = new System.Drawing.Point(6, 86); + this.akGammaLabel.Name = "akGammaLabel"; + this.akGammaLabel.Size = new System.Drawing.Size(102, 13); + this.akGammaLabel.TabIndex = 1; + this.akGammaLabel.Text = "Alpha mask gamma:"; + // + // akAlphaMaskGammaTrackBar + // + this.akAlphaMaskGammaTrackBar.LargeChange = 2; + this.akAlphaMaskGammaTrackBar.Location = new System.Drawing.Point(6, 102); + this.akAlphaMaskGammaTrackBar.Maximum = 5; + this.akAlphaMaskGammaTrackBar.Minimum = -5; + this.akAlphaMaskGammaTrackBar.Name = "akAlphaMaskGammaTrackBar"; + this.akAlphaMaskGammaTrackBar.Size = new System.Drawing.Size(288, 45); + this.akAlphaMaskGammaTrackBar.TabIndex = 0; + this.akAlphaMaskGammaTrackBar.Scroll += new System.EventHandler(this.akAlphaMaskGammaTrackBar_Scroll); + // + // akSpritesExportGroupBox + // + this.akSpritesExportGroupBox.Controls.Add(this.akAddAliasesCheckBox); + this.akSpritesExportGroupBox.Location = new System.Drawing.Point(537, 197); + this.akSpritesExportGroupBox.Name = "akSpritesExportGroupBox"; + this.akSpritesExportGroupBox.Size = new System.Drawing.Size(300, 178); + this.akSpritesExportGroupBox.TabIndex = 13; + this.akSpritesExportGroupBox.TabStop = false; + this.akSpritesExportGroupBox.Text = "Sprites: Export [Arknights]"; + // + // akAddAliasesCheckBox + // + this.akAddAliasesCheckBox.AutoSize = true; + this.akAddAliasesCheckBox.Location = new System.Drawing.Point(6, 28); + this.akAddAliasesCheckBox.Name = "akAddAliasesCheckBox"; + this.akAddAliasesCheckBox.Size = new System.Drawing.Size(213, 17); + this.akAddAliasesCheckBox.TabIndex = 0; + this.akAddAliasesCheckBox.Text = "Add aliases to avg sprite names (if exist)"; + this.akAddAliasesCheckBox.UseVisualStyleBackColor = true; + // // ExportOptions // this.AcceptButton = this.OKbutton; this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.CancelButton = this.Cancel; - this.ClientSize = new System.Drawing.Size(549, 416); + this.ClientSize = new System.Drawing.Size(849, 416); + this.Controls.Add(this.akSpritesExportGroupBox); + this.Controls.Add(this.akSpritesAlphaGroupBox); this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox1); this.Controls.Add(this.Cancel); @@ -521,6 +662,11 @@ ((System.ComponentModel.ISupportInitialize)(this.scaleFactor)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.boneSize)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.filterPrecision)).EndInit(); + this.akSpritesAlphaGroupBox.ResumeLayout(false); + this.akSpritesAlphaGroupBox.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.akAlphaMaskGammaTrackBar)).EndInit(); + this.akSpritesExportGroupBox.ResumeLayout(false); + this.akSpritesExportGroupBox.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -562,5 +708,16 @@ private System.Windows.Forms.ToolTip exportUvsTooltip; private System.Windows.Forms.CheckBox exportSpriteWithAlphaMask; private System.Windows.Forms.RadioButton towebp; + private System.Windows.Forms.GroupBox akSpritesAlphaGroupBox; + private System.Windows.Forms.TrackBar akAlphaMaskGammaTrackBar; + private System.Windows.Forms.Label akResamplerDescLabel; + private System.Windows.Forms.Label akResamplerLabel; + private System.Windows.Forms.ComboBox akResamplerComboBox; + private System.Windows.Forms.CheckBox akResizedOnlyCheckBox; + private System.Windows.Forms.Label akGammaValueLabel; + private System.Windows.Forms.Label akGammaLabel; + private System.Windows.Forms.GroupBox akSpritesExportGroupBox; + private System.Windows.Forms.CheckBox akAddAliasesCheckBox; + private System.Windows.Forms.Label akGammaNoteLabel; } } \ No newline at end of file diff --git a/AssetStudioGUI/ExportOptions.cs b/AssetStudioGUI/ExportOptions.cs index c3542a1..4b7717b 100644 --- a/AssetStudioGUI/ExportOptions.cs +++ b/AssetStudioGUI/ExportOptions.cs @@ -37,6 +37,13 @@ namespace AssetStudioGUI fbxVersion.SelectedIndex = Properties.Settings.Default.fbxVersion; fbxFormat.SelectedIndex = Properties.Settings.Default.fbxFormat; + //Arknights + akResamplerComboBox.SelectedIndex = Properties.Settings.Default.resamplerIndex; + akAlphaMaskGammaTrackBar.Value = Properties.Settings.Default.alphaMaskGamma; + akGammaValueLabel.Text = akAlphaMaskGammaTrackBar.Value == 0 ? "Default" : $"{akAlphaMaskGammaTrackBar.Value * 10:+#;-#;0}%"; + akResizedOnlyCheckBox.Checked = Properties.Settings.Default.resizedOnly; + akAddAliasesCheckBox.Checked = Properties.Settings.Default.addAliases; + } private void OKbutton_Click(object sender, EventArgs e) @@ -67,11 +74,24 @@ namespace AssetStudioGUI Properties.Settings.Default.scaleFactor = scaleFactor.Value; Properties.Settings.Default.fbxVersion = fbxVersion.SelectedIndex; Properties.Settings.Default.fbxFormat = fbxFormat.SelectedIndex; + + //Arknights + Properties.Settings.Default.resamplerIndex = akResamplerComboBox.SelectedIndex; + Properties.Settings.Default.alphaMaskGamma = akAlphaMaskGammaTrackBar.Value; + Properties.Settings.Default.resizedOnly = akResizedOnlyCheckBox.Checked; + Properties.Settings.Default.addAliases = akAddAliasesCheckBox.Checked; + Properties.Settings.Default.Save(); DialogResult = DialogResult.OK; Close(); } + //Arknights + private void akAlphaMaskGammaTrackBar_Scroll(object sender, EventArgs e) + { + akGammaValueLabel.Text = akAlphaMaskGammaTrackBar.Value == 0 ? "Default" : $"{akAlphaMaskGammaTrackBar.Value * 10:+#;-#;0}%"; + } + private void Cancel_Click(object sender, EventArgs e) { DialogResult = DialogResult.Cancel; diff --git a/AssetStudioGUI/Exporter.cs b/AssetStudioGUI/Exporter.cs index 1621bc7..18ff32f 100644 --- a/AssetStudioGUI/Exporter.cs +++ b/AssetStudioGUI/Exporter.cs @@ -1,4 +1,7 @@ -using AssetStudio; +using Arknights; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using AssetStudio; using Newtonsoft.Json; using System.Collections.Generic; using System.IO; @@ -239,11 +242,46 @@ namespace AssetStudioGUI public static bool ExportSprite(AssetItem item, string exportPath) { - var type = Properties.Settings.Default.convertType; + Image image; + AvgSprite avgSprite = null; + var alias = ""; + var m_Sprite = (Sprite)item.Asset; var spriteMaskMode = Properties.Settings.Default.exportSpriteWithMask ? SpriteMaskMode.Export : SpriteMaskMode.Off; - if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath)) + var type = Properties.Settings.Default.convertType; + var isCharAvgSprite = item.Container.Contains("avg/characters"); + var isCharArt = item.Container.Contains("arts/characters"); + + if (isCharAvgSprite) + { + avgSprite = new AvgSprite(item); + + if (Properties.Settings.Default.addAliases && !string.IsNullOrEmpty(avgSprite.Alias)) + { + alias = $"_{avgSprite.Alias}"; + } + } + + if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath, alias)) return false; - var image = ((Sprite)item.Asset).GetImage(spriteMaskMode: spriteMaskMode); + + if (Properties.Settings.Default.useExternalAlpha && (isCharAvgSprite || isCharArt)) + { + if (m_Sprite.m_RD.alphaTexture.IsNull) + { + var charAlphaAtlas = AkSpriteHelper.TryFindAlphaTex(item, avgSprite, isCharAvgSprite); + if (charAlphaAtlas != null) + { + m_Sprite.m_RD.alphaTexture.Set(charAlphaAtlas); + m_Sprite.akSplitAlpha = true; + } + } + image = m_Sprite.AkGetImage(avgSprite, spriteMaskMode: spriteMaskMode); + } + else + { + image = m_Sprite.GetImage(spriteMaskMode: spriteMaskMode); + } + if (image != null) { using (image) @@ -266,9 +304,9 @@ namespace AssetStudioGUI return true; } - private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath) + private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath, string alias = "") { - var fileName = FixFileName(item.Text); + var fileName = FixFileName(item.Text) + alias; fullPath = Path.Combine(dir, fileName + extension); if (!File.Exists(fullPath)) { diff --git a/AssetStudioGUI/Properties/Settings.Designer.cs b/AssetStudioGUI/Properties/Settings.Designer.cs index 9ba3bcf..d83b923 100644 --- a/AssetStudioGUI/Properties/Settings.Designer.cs +++ b/AssetStudioGUI/Properties/Settings.Designer.cs @@ -286,5 +286,77 @@ namespace AssetStudioGUI.Properties { this["exportSpriteWithMask"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool fixFaceSpriteNames { + get { + return ((bool)(this["fixFaceSpriteNames"])); + } + set { + this["fixFaceSpriteNames"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool useExternalAlpha { + get { + return ((bool)(this["useExternalAlpha"])); + } + set { + this["useExternalAlpha"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool addAliases { + get { + return ((bool)(this["addAliases"])); + } + set { + this["addAliases"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("3")] + public int resamplerIndex { + get { + return ((int)(this["resamplerIndex"])); + } + set { + this["resamplerIndex"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool resizedOnly { + get { + return ((bool)(this["resizedOnly"])); + } + set { + this["resizedOnly"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("2")] + public int alphaMaskGamma { + get { + return ((int)(this["alphaMaskGamma"])); + } + set { + this["alphaMaskGamma"] = value; + } + } } } diff --git a/AssetStudioGUI/Properties/Settings.settings b/AssetStudioGUI/Properties/Settings.settings index aef06e0..0746d55 100644 --- a/AssetStudioGUI/Properties/Settings.settings +++ b/AssetStudioGUI/Properties/Settings.settings @@ -68,5 +68,23 @@ True + + True + + + True + + + False + + + 3 + + + True + + + 2 + \ No newline at end of file diff --git a/AssetStudioUtility/SpriteHelper.cs b/AssetStudioUtility/SpriteHelper.cs index 8d6d735..d82b638 100644 --- a/AssetStudioUtility/SpriteHelper.cs +++ b/AssetStudioUtility/SpriteHelper.cs @@ -32,7 +32,7 @@ namespace AssetStudio } else { - if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D) && m_Sprite.m_RD.alphaTexture.TryGet(out var m_AlphaTexture2D) && spriteMaskMode != SpriteMaskMode.Off) + if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D) && m_Sprite.m_RD.alphaTexture.TryGet(out var m_AlphaTexture2D) && spriteMaskMode != SpriteMaskMode.Off && !m_Sprite.akSplitAlpha) { 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);