using Arknights.AvgCharHubMono; using AssetStudio; using AssetStudioGUI; using SixLabors.ImageSharp; using System.Linq; using System; using System.Collections.Specialized; 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 scriptAssets = Studio.exportableAssets.FindAll(x => x.Type == ClassIDType.MonoBehaviour && x.Container == assetItem.Container); if (scriptAssets.Count == 0) { Logger.Warning("No MonoBehaviours were found."); return false; } OrderedDictionary spriteHubDict = null; var isGrouped = false; foreach (var scriptAsset in scriptAssets) { var scriptAssetDict = ((MonoBehaviour)scriptAsset.Asset).ToType(); if (scriptAssetDict == null) { Logger.Warning("MonoBehaviour is not readable."); return false; } if (scriptAssetDict.Contains("spriteGroups")) { spriteHubDict = scriptAssetDict; isGrouped = true; break; } if (scriptAssetDict.Contains("sprites")) { spriteHubDict = scriptAssetDict; break; } } if (spriteHubDict == null) { Logger.Warning("AVGCharacterSpriteHub is not readable."); return false; } var spriteHubJson = JsonConvert.SerializeObject(spriteHubDict); if (isGrouped) { 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) //If face data exist { var fullTexSpriteData = spriteHubData.Sprites.Last(); //Last sprite item in the list usually contains PathID of Sprite with full texture var curSprite = (Sprite)assetItem.Asset; IsFaceSprite = curSprite.m_Rect.width <= 256 && curSprite.m_Rect.height <= 256 && curSprite.m_PathID != fullTexSpriteData.Sprite.m_PathID; var curSpriteAlphaID = curSpriteData.AlphaTex.m_PathID; var curSpriteAlphaTex = (Texture2D)Studio.exportableAssets.Find(x => x.m_PathID == curSpriteAlphaID)?.Asset; if (curSpriteAlphaTex != null) { FaceSpriteAlphaTexture = IsFaceSprite ? curSpriteAlphaTex : null; fullTexSpriteData = IsFaceSprite ? fullTexSpriteData : curSpriteData; } 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)); } else { FullAlphaTexture = (Texture2D)Studio.exportableAssets.Find(x => x.m_PathID == curSpriteData.AlphaTex.m_PathID)?.Asset; } } } } }