From 7321cf978063dfc638aef57633de9a0b2f4ac730 Mon Sep 17 00:00:00 2001 From: Razmoth <32140579+Razmoth@users.noreply.github.com> Date: Thu, 30 Nov 2023 10:23:47 +0400 Subject: [PATCH] - [Core] Combine `ModelConverter` options. - [Core] Fix bug with loading `.zip` files - [Core] Added new entry [UnityCN] --- AssetStudio.CLI/Exporter.cs | 24 ++++++++-- AssetStudio.GUI/Exporter.cs | 36 ++++++++++++--- AssetStudio.GUI/MainForm.cs | 20 +++++++- AssetStudio.Utility/ModelConverter.cs | 66 +++++++++++++-------------- AssetStudio/AssetsManager.cs | 1 + AssetStudio/Keys.json | 4 ++ 6 files changed, 106 insertions(+), 45 deletions(-) diff --git a/AssetStudio.CLI/Exporter.cs b/AssetStudio.CLI/Exporter.cs index d651649..deb2f8d 100644 --- a/AssetStudio.CLI/Exporter.cs +++ b/AssetStudio.CLI/Exporter.cs @@ -335,9 +335,17 @@ namespace AssetStudio.CLI exportFullPath = Path.Combine(exportPath, item.Text + item.UniqueID, item.Text + ".fbx"); } var m_Animator = (Animator)item.Asset; + var options = new ModelConverter.Options() + { + imageFormat = Properties.Settings.Default.convertType, + game = Studio.Game, + collectAnimations = Properties.Settings.Default.collectAnimations, + uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs), + texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs), + }; var convert = animationList != null - ? new ModelConverter(m_Animator, Properties.Settings.Default.convertType, Properties.Settings.Default.texs, Properties.Settings.Default.uvs, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) - : new ModelConverter(m_Animator, Properties.Settings.Default.convertType, Properties.Settings.Default.texs, Properties.Settings.Default.uvs, Studio.Game, Properties.Settings.Default.collectAnimations); + ? new ModelConverter(m_Animator, options, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) + : new ModelConverter(m_Animator, options); ExportFbx(convert, exportFullPath); return true; } @@ -351,9 +359,17 @@ namespace AssetStudio.CLI public static bool ExportGameObject(GameObject gameObject, string exportPath, List animationList = null) { + var options = new ModelConverter.Options() + { + imageFormat = Properties.Settings.Default.convertType, + game = Studio.Game, + collectAnimations = Properties.Settings.Default.collectAnimations, + uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs), + texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs), + }; var convert = animationList != null - ? new ModelConverter(gameObject, Properties.Settings.Default.convertType, Properties.Settings.Default.texs, Properties.Settings.Default.uvs, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) - : new ModelConverter(gameObject, Properties.Settings.Default.convertType, Properties.Settings.Default.texs, Properties.Settings.Default.uvs, Studio.Game, Properties.Settings.Default.collectAnimations); + ? new ModelConverter(gameObject, options, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) + : new ModelConverter(gameObject, options); if (convert.MeshList.Count == 0) { diff --git a/AssetStudio.GUI/Exporter.cs b/AssetStudio.GUI/Exporter.cs index dc4c8fe..02eba55 100644 --- a/AssetStudio.GUI/Exporter.cs +++ b/AssetStudio.GUI/Exporter.cs @@ -334,9 +334,17 @@ namespace AssetStudio.GUI exportFullPath = Path.Combine(exportPath, item.Text + item.UniqueID, item.Text + ".fbx"); } var m_Animator = (Animator)item.Asset; + var options = new ModelConverter.Options() + { + imageFormat = Properties.Settings.Default.convertType, + game = Studio.Game, + collectAnimations = Properties.Settings.Default.collectAnimations, + uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs), + texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs), + }; var convert = animationList != null - ? new ModelConverter(m_Animator, Properties.Settings.Default.convertType, Properties.Settings.Default.texs, Properties.Settings.Default.uvs, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) - : new ModelConverter(m_Animator, Properties.Settings.Default.convertType, Properties.Settings.Default.texs, Properties.Settings.Default.uvs, Studio.Game, Properties.Settings.Default.collectAnimations); + ? new ModelConverter(m_Animator, options, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) + : new ModelConverter(m_Animator, options); ExportFbx(convert, exportFullPath); return true; } @@ -355,9 +363,17 @@ namespace AssetStudio.GUI public static void ExportGameObject(GameObject gameObject, string exportPath, List animationList = null) { + var options = new ModelConverter.Options() + { + imageFormat = Properties.Settings.Default.convertType, + game = Studio.Game, + collectAnimations = Properties.Settings.Default.collectAnimations, + uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs), + texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs), + }; var convert = animationList != null - ? new ModelConverter(gameObject, Properties.Settings.Default.convertType, Properties.Settings.Default.texs, Properties.Settings.Default.uvs, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) - : new ModelConverter(gameObject, Properties.Settings.Default.convertType, Properties.Settings.Default.texs, Properties.Settings.Default.uvs, Studio.Game, Properties.Settings.Default.collectAnimations); + ? new ModelConverter(gameObject, options, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) + : new ModelConverter(gameObject, options); exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx"; ExportFbx(convert, exportPath); } @@ -365,9 +381,17 @@ namespace AssetStudio.GUI public static void ExportGameObjectMerge(List gameObject, string exportPath, List animationList = null) { var rootName = Path.GetFileNameWithoutExtension(exportPath); + var options = new ModelConverter.Options() + { + imageFormat = Properties.Settings.Default.convertType, + game = Studio.Game, + collectAnimations = Properties.Settings.Default.collectAnimations, + uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs), + texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs), + }; var convert = animationList != null - ? new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, Properties.Settings.Default.texs, Properties.Settings.Default.uvs, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) - : new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, Properties.Settings.Default.texs, Properties.Settings.Default.uvs, Studio.Game, Properties.Settings.Default.collectAnimations); + ? new ModelConverter(rootName, gameObject, options, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) + : new ModelConverter(rootName, gameObject, options); ExportFbx(convert, exportPath); } diff --git a/AssetStudio.GUI/MainForm.cs b/AssetStudio.GUI/MainForm.cs index ab92486..38e62d8 100644 --- a/AssetStudio.GUI/MainForm.cs +++ b/AssetStudio.GUI/MainForm.cs @@ -1290,12 +1290,28 @@ namespace AssetStudio.GUI private void PreviewGameObject(GameObject m_GameObject) { - var model = new ModelConverter(m_GameObject, Properties.Settings.Default.convertType, Properties.Settings.Default.texs, Properties.Settings.Default.uvs, Studio.Game, false, Array.Empty()); + var options = new ModelConverter.Options() + { + imageFormat = Properties.Settings.Default.convertType, + game = Studio.Game, + collectAnimations = Properties.Settings.Default.collectAnimations, + uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs), + texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs), + }; + var model = new ModelConverter(m_GameObject, options, Array.Empty()); PreviewModel(model); } private void PreviewAnimator(Animator m_Animator) { - var model = new ModelConverter(m_Animator, Properties.Settings.Default.convertType, Properties.Settings.Default.texs, Properties.Settings.Default.uvs, Studio.Game, false, Array.Empty()); + var options = new ModelConverter.Options() + { + imageFormat = Properties.Settings.Default.convertType, + game = Studio.Game, + collectAnimations = Properties.Settings.Default.collectAnimations, + uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs), + texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs), + }; + var model = new ModelConverter(m_Animator, options, Array.Empty()); PreviewModel(model); } diff --git a/AssetStudio.Utility/ModelConverter.cs b/AssetStudio.Utility/ModelConverter.cs index 4487a12..f9d820c 100644 --- a/AssetStudio.Utility/ModelConverter.cs +++ b/AssetStudio.Utility/ModelConverter.cs @@ -15,8 +15,7 @@ namespace AssetStudio public List AnimationList { get; protected set; } = new List(); public List MorphList { get; protected set; } = new List(); - private Game Game; - private ImageFormat imageFormat; + private Options options; private Avatar avatar; private HashSet animationClipHashSet = new HashSet(); private Dictionary boundAnimationPathDic = new Dictionary(); @@ -24,19 +23,15 @@ namespace AssetStudio private Dictionary textureNameDictionary = new Dictionary(); private Dictionary transformDictionary = new Dictionary(); Dictionary morphChannelNames = new Dictionary(); - Dictionary uvs = new Dictionary(); - Dictionary texs = new Dictionary(); - public ModelConverter(GameObject m_GameObject, ImageFormat imageFormat, string texs, string uvs, Game game, bool collectAnimations, AnimationClip[] animationList = null) + public ModelConverter(GameObject m_GameObject, Options options, AnimationClip[] animationList = null) { - Game = game; - this.imageFormat = imageFormat; - this.texs = JsonConvert.DeserializeObject>(texs); - this.uvs = JsonConvert.DeserializeObject>(uvs); + this.options = options; + if (m_GameObject.m_Animator != null) { InitWithAnimator(m_GameObject.m_Animator); - if (animationList == null && collectAnimations) + if (animationList == null && this.options.collectAnimations) { CollectAnimationClip(m_GameObject.m_Animator); } @@ -55,16 +50,14 @@ namespace AssetStudio ConvertAnimations(); } - public ModelConverter(string rootName, List m_GameObjects, ImageFormat imageFormat, string texs, string uvs, Game game, bool collectAnimations, AnimationClip[] animationList = null) + public ModelConverter(string rootName, List m_GameObjects, Options options, AnimationClip[] animationList = null) { - Game = game; - this.imageFormat = imageFormat; - this.texs = JsonConvert.DeserializeObject>(texs); - this.uvs = JsonConvert.DeserializeObject>(uvs); + this.options = options; + RootFrame = CreateFrame(rootName, Vector3.Zero, new Quaternion(0, 0, 0, 0), Vector3.One); foreach (var m_GameObject in m_GameObjects) { - if (m_GameObject.m_Animator != null && animationList == null && collectAnimations) + if (m_GameObject.m_Animator != null && animationList == null && this.options.collectAnimations) { CollectAnimationClip(m_GameObject.m_Animator); } @@ -88,14 +81,12 @@ namespace AssetStudio ConvertAnimations(); } - public ModelConverter(Animator m_Animator, ImageFormat imageFormat, string texs, string uvs, Game game, bool collectAnimations, AnimationClip[] animationList = null) + public ModelConverter(Animator m_Animator, Options options, AnimationClip[] animationList = null) { - Game = game; - this.imageFormat = imageFormat; - this.texs = JsonConvert.DeserializeObject>(texs); - this.uvs = JsonConvert.DeserializeObject>(uvs); + this.options = options; + InitWithAnimator(m_Animator); - if (animationList == null && collectAnimations) + if (animationList == null && this.options.collectAnimations) { CollectAnimationClip(m_Animator); } @@ -313,8 +304,8 @@ namespace AssetStudio for (int uv = 0; uv < 8; uv++) { var key = $"UV{uv}"; - iMesh.hasUV[uv] = mesh.GetUV(uv)?.Length > 0 && uvs[key].Item1; - iMesh.uvType[uv] = uvs[key].Item2; + iMesh.hasUV[uv] = mesh.GetUV(uv)?.Length > 0 && options.uvs[key].Item1; + iMesh.uvType[uv] = options.uvs[key].Item2; } iMesh.hasTangent = mesh.m_Tangents != null && mesh.m_Tangents.Length == mesh.m_VertexCount * 4; iMesh.hasColor = mesh.m_Colors?.Length > 0; @@ -720,7 +711,7 @@ namespace AssetStudio iMat.Textures.Add(texture); int dest = -1; - if (texs.TryGetValue(texEnv.Key, out var targetDest)) + if (options.texs.TryGetValue(texEnv.Key, out var targetDest)) dest = targetDest; else if (texEnv.Key == "_MainTex") dest = 0; @@ -733,7 +724,7 @@ namespace AssetStudio texture.Dest = dest; - var ext = $".{imageFormat.ToString().ToLower()}"; + var ext = $".{options.imageFormat.ToString().ToLower()}"; if (textureNameDictionary.TryGetValue(m_Texture2D, out var textureName)) { texture.Name = textureName; @@ -779,7 +770,7 @@ namespace AssetStudio return; } - var stream = m_Texture2D.ConvertToStream(imageFormat, true); + var stream = m_Texture2D.ConvertToStream(options.imageFormat, true); if (stream != null) { using (stream) @@ -909,9 +900,9 @@ namespace AssetStudio var m_ClipBindingConstant = animationClip.m_ClipBindingConstant ?? m_Clip.ConvertValueArrayToGenericBinding(); var m_ACLClip = m_Clip.m_ACLClip; var aclCount = m_ACLClip.CurveCount; - if (m_ACLClip.IsSet && !Game.Type.IsSRGroup()) + if (m_ACLClip.IsSet && !options.game.Type.IsSRGroup()) { - m_ACLClip.Process(Game, out var values, out var times); + m_ACLClip.Process(options.game, out var values, out var times); for (int frameIndex = 0; frameIndex < times.Length; frameIndex++) { var time = times[frameIndex]; @@ -931,7 +922,7 @@ namespace AssetStudio for (int curveIndex = 0; curveIndex < frame.keyList.Count;) { var index = frame.keyList[curveIndex].index; - if (!Game.Type.IsSRGroup()) + if (!options.game.Type.IsSRGroup()) index += (int)aclCount; ReadCurveData(iAnim, m_ClipBindingConstant, index, frame.time, streamedValues, 0, ref curveIndex); } @@ -945,14 +936,14 @@ namespace AssetStudio for (int curveIndex = 0; curveIndex < m_DenseClip.m_CurveCount;) { var index = streamCount + curveIndex; - if (!Game.Type.IsSRGroup()) + if (!options.game.Type.IsSRGroup()) index += (int)aclCount; ReadCurveData(iAnim, m_ClipBindingConstant, (int)index, time, m_DenseClip.m_SampleArray, (int)frameOffset, ref curveIndex); } } - if (m_ACLClip.IsSet && Game.Type.IsSRGroup()) + if (m_ACLClip.IsSet && options.game.Type.IsSRGroup()) { - m_ACLClip.Process(Game, out var values, out var times); + m_ACLClip.Process(options.game, out var values, out var times); for (int frameIndex = 0; frameIndex < times.Length; frameIndex++) { var time = times[frameIndex]; @@ -1174,5 +1165,14 @@ namespace AssetStudio return null; } } + + public record Options + { + public ImageFormat imageFormat; + public Game game; + public bool collectAnimations; + public Dictionary uvs; + public Dictionary texs; + } } } diff --git a/AssetStudio/AssetsManager.cs b/AssetStudio/AssetsManager.cs index 5665610..76343ed 100644 --- a/AssetStudio/AssetsManager.cs +++ b/AssetStudio/AssetsManager.cs @@ -402,6 +402,7 @@ namespace AssetStudio streamReader.Position = 0; FileReader entryReader = new FileReader(dummyPath, streamReader); + entryReader = entryReader.PreProcessing(Game); LoadFile(entryReader); if (entryReader.FileType == FileType.ResourceFile) { diff --git a/AssetStudio/Keys.json b/AssetStudio/Keys.json index 5f72d4a..f9cdd9b 100644 --- a/AssetStudio/Keys.json +++ b/AssetStudio/Keys.json @@ -82,5 +82,9 @@ { "Name": "Frostpunk: Beyond the Ice", "Key": "7368756978696E673838383838383838" + }, + { + "Name": "Cat Fantasy", + "Key": "43614461566637323538576877363433" } ]