mirror of
https://github.com/aelurum/AssetStudio.git
synced 2025-06-03 00:58:13 -04:00
[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:
parent
94c8b355fe
commit
abbd27fde7
@ -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
|
||||
}
|
||||
}
|
||||
|
67
AssetStudioGUI/AssetStudioGUIForm.Designer.cs
generated
67
AssetStudioGUI/AssetStudioGUIForm.Designer.cs
generated
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
200
AssetStudioGUI/Components/Arknights/AkSpriteHelper.cs
Normal file
200
AssetStudioGUI/Components/Arknights/AkSpriteHelper.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
125
AssetStudioGUI/Components/Arknights/AvgSprite.cs
Normal file
125
AssetStudioGUI/Components/Arknights/AvgSprite.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
30
AssetStudioGUI/Components/Arknights/AvgSpriteConfig.cs
Normal file
30
AssetStudioGUI/Components/Arknights/AvgSpriteConfig.cs
Normal 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; }
|
||||
}
|
||||
}
|
163
AssetStudioGUI/ExportOptions.Designer.cs
generated
163
AssetStudioGUI/ExportOptions.Designer.cs
generated
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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))
|
||||
{
|
||||
|
72
AssetStudioGUI/Properties/Settings.Designer.cs
generated
72
AssetStudioGUI/Properties/Settings.Designer.cs
generated
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user