[AK][GUI] Add support for sprites with an external alpha texture

- Added support for Arknights chararts sprites
- Added support for Arknights avg sprites
This commit is contained in:
VaDiM 2023-08-14 20:25:48 +03:00
parent 94c8b355fe
commit abbd27fde7
12 changed files with 849 additions and 20 deletions

View File

@ -205,6 +205,7 @@ namespace AssetStudio
public PPtr<SpriteAtlas> 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
}
}

View File

@ -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;
}
}

View File

@ -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<SharpImageFormat.Bgra32> 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();

View File

@ -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<Bgra32> 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<Bgra32> tex;
Image<Bgra32> 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<Bgra32> tex, Image<Bgra32> 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<Bgra32> CutImage(Image<Bgra32> 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;
}
}
}

View File

@ -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<AvgSpriteConfigGroup>(spriteHubJson);
spriteHubData = GetCurSpriteGroup(groupedSpriteHub, assetItem.m_PathID, assetItem.Text);
}
else
{
spriteHubData = JsonConvert.DeserializeObject<AvgSpriteConfig>(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;
}
}
}
}
}

View File

@ -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; }
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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<Bgra32> 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))
{

View File

@ -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;
}
}
}
}

View File

@ -68,5 +68,23 @@
<Setting Name="exportSpriteWithMask" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="fixFaceSpriteNames" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="useExternalAlpha" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="addAliases" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="resamplerIndex" Type="System.Int32" Scope="User">
<Value Profile="(Default)">3</Value>
</Setting>
<Setting Name="resizedOnly" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="alphaMaskGamma" Type="System.Int32" Scope="User">
<Value Profile="(Default)">2</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@ -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);