diff --git a/AssetStudio.CLI/App.config b/AssetStudio.CLI/App.config index 89578f6..0ce2b33 100644 --- a/AssetStudio.CLI/App.config +++ b/AssetStudio.CLI/App.config @@ -10,6 +10,7 @@ + @@ -21,7 +22,7 @@ - + diff --git a/AssetStudio.CLI/Exporter.cs b/AssetStudio.CLI/Exporter.cs index 6ec097b..36044a0 100644 --- a/AssetStudio.CLI/Exporter.cs +++ b/AssetStudio.CLI/Exporter.cs @@ -365,12 +365,24 @@ namespace AssetStudio.CLI imageFormat = Properties.Settings.Default.convertType, game = Studio.Game, collectAnimations = Properties.Settings.Default.collectAnimations, + exportMaterials = Properties.Settings.Default.exportMaterials, + materials = new HashSet(), uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs), texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs), }; var convert = animationList != null ? new ModelConverter(m_Animator, options, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) : new ModelConverter(m_Animator, options); + if (options.exportMaterials) + { + var materialExportPath = Path.Combine(exportFullPath, "Materials"); + Directory.CreateDirectory(materialExportPath); + foreach (var material in options.materials) + { + var matItem = new AssetItem(material); + ExportJSONFile(matItem, materialExportPath); + } + } ExportFbx(convert, exportFullPath); return true; } @@ -391,6 +403,8 @@ namespace AssetStudio.CLI imageFormat = Properties.Settings.Default.convertType, game = Studio.Game, collectAnimations = Properties.Settings.Default.collectAnimations, + exportMaterials = Properties.Settings.Default.exportMaterials, + materials = new HashSet(), uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs), texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs), }; @@ -403,6 +417,16 @@ namespace AssetStudio.CLI Logger.Info($"GameObject {gameObject.m_Name} has no mesh, skipping..."); return false; } + if (options.exportMaterials) + { + var materialExportPath = Path.Combine(exportPath, "Materials"); + Directory.CreateDirectory(materialExportPath); + foreach (var material in options.materials) + { + var matItem = new AssetItem(material); + ExportJSONFile(matItem, materialExportPath); + } + } exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx"; ExportFbx(convert, exportPath); return true; diff --git a/AssetStudio.CLI/Program.cs b/AssetStudio.CLI/Program.cs index 43890c8..26dbca1 100644 --- a/AssetStudio.CLI/Program.cs +++ b/AssetStudio.CLI/Program.cs @@ -40,7 +40,8 @@ namespace AssetStudio.CLI } Studio.Game = game; - Logger.Default = new ConsoleLogger() { Flags = o.LoggerFlags.Aggregate((e, x) => e |= x) }; + Logger.Default = new ConsoleLogger(); + Logger.Flags = o.LoggerFlags.Aggregate((e, x) => e |= x); Logger.FileLogging = Settings.Default.enableFileLogging; AssetsHelper.Minimal = Settings.Default.minimalAssetMap; AssetsHelper.SetUnityVersion(o.UnityVersion); @@ -67,6 +68,10 @@ namespace AssetStudio.CLI { TypeFlags.SetType(ClassIDType.GameObject, true, false); } + if (Settings.Default.exportMaterials) + { + TypeFlags.SetType(ClassIDType.Material, true, false); + } } } diff --git a/AssetStudio.CLI/Settings.cs b/AssetStudio.CLI/Settings.cs index e769c84..d3fee78 100644 --- a/AssetStudio.CLI/Settings.cs +++ b/AssetStudio.CLI/Settings.cs @@ -43,6 +43,7 @@ namespace AssetStudio.CLI.Properties { public decimal filterPrecision => AppSettings.Get("filterPrecision", (decimal)0.25); public bool exportAllNodes => AppSettings.Get("exportAllNodes", true); public bool exportSkins => AppSettings.Get("exportSkins", true); + public bool exportMaterials => AppSettings.Get("exportMaterials", false); public bool collectAnimations => AppSettings.Get("collectAnimations", true); public bool exportAnimations => AppSettings.Get("exportAnimations", true); public decimal boneSize => AppSettings.Get("boneSize", (decimal)10); diff --git a/AssetStudio.GUI/App.config b/AssetStudio.GUI/App.config index 87366b3..49cc43e 100644 --- a/AssetStudio.GUI/App.config +++ b/AssetStudio.GUI/App.config @@ -1,126 +1,3 @@  - - -
- - - - - - False - - - True - - - True - - - True - - - 0 - - - True - - - True - - - True - - - 0.25 - - - True - - - True - - - True - - - 10 - - - 3 - - - 0 - - - 1 - - - True - - - False - - - True - - - 147 - - - True - - - True - - - 0 - - - True - - - 1 - - - True - - - False - - - True - - - False - - - False - - - 0 - - - - - - True - - - {"UV0":{"Item1":true,"Item2":0},"UV1":{"Item1":true,"Item2":1},"UV2":{"Item1":false,"Item2":0},"UV3":{"Item1":false,"Item2":0},"UV4":{"Item1":false,"Item2":0},"UV5":{"Item1":false,"Item2":0},"UV6":{"Item1":false,"Item2":0},"UV7":{"Item1":false,"Item2":0}} - - - False - - - 30 - - - {"Animation":{"Item1":true,"Item2":false},"AnimationClip":{"Item1":true,"Item2":true},"Animator":{"Item1":true,"Item2":true},"AnimatorController":{"Item1":true,"Item2":false},"AnimatorOverrideController":{"Item1":true,"Item2":false},"AssetBundle":{"Item1":true,"Item2":false},"AudioClip":{"Item1":true,"Item2":true},"Avatar":{"Item1":true,"Item2":false},"Font":{"Item1":true,"Item2":true},"GameObject":{"Item1":true,"Item2":false},"IndexObject":{"Item1":true,"Item2":false},"Material":{"Item1":true,"Item2":true},"Mesh":{"Item1":true,"Item2":true},"MeshFilter":{"Item1":true,"Item2":false},"MeshRenderer":{"Item1":true,"Item2":false},"MiHoYoBinData":{"Item1":true,"Item2":true},"MonoBehaviour":{"Item1":true,"Item2":true},"MonoScript":{"Item1":true,"Item2":false},"MovieTexture":{"Item1":true,"Item2":true},"PlayerSettings":{"Item1":true,"Item2":false},"RectTransform":{"Item1":true,"Item2":false},"Shader":{"Item1":true,"Item2":true},"SkinnedMeshRenderer":{"Item1":true,"Item2":false},"Sprite":{"Item1":true,"Item2":true},"SpriteAtlas":{"Item1":true,"Item2":false},"TextAsset":{"Item1":true,"Item2":true},"Texture2D":{"Item1":true,"Item2":true},"Transform":{"Item1":true,"Item2":false},"VideoClip":{"Item1":true,"Item2":true},"ResourceManager":{"Item1":true,"Item2":false}} - - - - - - \ No newline at end of file diff --git a/AssetStudio.GUI/ExportOptions.Designer.cs b/AssetStudio.GUI/ExportOptions.Designer.cs index 7773ad9..b3d11be 100644 --- a/AssetStudio.GUI/ExportOptions.Designer.cs +++ b/AssetStudio.GUI/ExportOptions.Designer.cs @@ -66,6 +66,7 @@ namespace AssetStudio.GUI converttexture = new CheckBox(); collectAnimations = new CheckBox(); groupBox2 = new GroupBox(); + exportMaterials = new CheckBox(); exportBlendShape = new CheckBox(); exportAnimations = new CheckBox(); scaleFactor = new NumericUpDown(); @@ -471,6 +472,7 @@ namespace AssetStudio.GUI // groupBox2 // groupBox2.AutoSize = true; + groupBox2.Controls.Add(exportMaterials); groupBox2.Controls.Add(collectAnimations); groupBox2.Controls.Add(exportBlendShape); groupBox2.Controls.Add(exportAnimations); @@ -497,6 +499,17 @@ namespace AssetStudio.GUI groupBox2.TabStop = false; groupBox2.Text = "Fbx"; // + // exportMaterials + // + exportMaterials.AutoSize = true; + exportMaterials.Location = new System.Drawing.Point(154, 96); + exportMaterials.Margin = new Padding(4); + exportMaterials.Name = "exportMaterials"; + exportMaterials.Size = new System.Drawing.Size(111, 19); + exportMaterials.TabIndex = 25; + exportMaterials.Text = "Export materials"; + exportMaterials.UseVisualStyleBackColor = true; + // // exportBlendShape // exportBlendShape.AutoSize = true; @@ -780,5 +793,6 @@ namespace AssetStudio.GUI private ComboBox texNameComboBox; private Button addTexNameButton; private Button removeTexNameButton; + private CheckBox exportMaterials; } } diff --git a/AssetStudio.GUI/ExportOptions.cs b/AssetStudio.GUI/ExportOptions.cs index 98cea48..6ef16a3 100644 --- a/AssetStudio.GUI/ExportOptions.cs +++ b/AssetStudio.GUI/ExportOptions.cs @@ -1,6 +1,8 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.ComponentModel; +using System.Configuration; using System.Linq; using System.Text; using System.Windows.Forms; @@ -34,6 +36,7 @@ namespace AssetStudio.GUI filterPrecision.Value = Properties.Settings.Default.filterPrecision; exportAllNodes.Checked = Properties.Settings.Default.exportAllNodes; exportSkins.Checked = Properties.Settings.Default.exportSkins; + exportMaterials.Checked = Properties.Settings.Default.exportMaterials; exportAnimations.Checked = Properties.Settings.Default.exportAnimations; exportBlendShape.Checked = Properties.Settings.Default.exportBlendShape; castToBone.Checked = Properties.Settings.Default.castToBone; @@ -84,6 +87,7 @@ namespace AssetStudio.GUI Properties.Settings.Default.filterPrecision = filterPrecision.Value; Properties.Settings.Default.exportAllNodes = exportAllNodes.Checked; Properties.Settings.Default.exportSkins = exportSkins.Checked; + Properties.Settings.Default.exportMaterials = exportMaterials.Checked; Properties.Settings.Default.exportAnimations = exportAnimations.Checked; Properties.Settings.Default.exportBlendShape = exportBlendShape.Checked; Properties.Settings.Default.castToBone = castToBone.Checked; @@ -251,7 +255,12 @@ namespace AssetStudio.GUI private void Reset_Click(object sender, EventArgs e) { - Properties.Settings.Default.Reset(); + foreach(SettingsProperty settingsProperty in Properties.Settings.Default.Properties) + { + Properties.Settings.Default[settingsProperty.Name] = TypeDescriptor.GetConverter(settingsProperty.PropertyType).ConvertFrom(settingsProperty.DefaultValue); + } + Properties.Settings.Default.Save(); + DialogResult = DialogResult.Cancel; Resetted = true; Close(); diff --git a/AssetStudio.GUI/Exporter.cs b/AssetStudio.GUI/Exporter.cs index 29086d6..398a521 100644 --- a/AssetStudio.GUI/Exporter.cs +++ b/AssetStudio.GUI/Exporter.cs @@ -364,12 +364,24 @@ namespace AssetStudio.GUI imageFormat = Properties.Settings.Default.convertType, game = Studio.Game, collectAnimations = Properties.Settings.Default.collectAnimations, + exportMaterials = Properties.Settings.Default.exportMaterials, + materials = new HashSet(), uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs), texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs), }; var convert = animationList != null ? new ModelConverter(m_Animator, options, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) : new ModelConverter(m_Animator, options); + if (options.exportMaterials) + { + var materialExportPath = Path.Combine(exportFullPath, "Materials"); + Directory.CreateDirectory(materialExportPath); + foreach (var material in options.materials) + { + var matItem = new AssetItem(material); + ExportJSONFile(matItem, materialExportPath); + } + } ExportFbx(convert, exportFullPath); return true; } @@ -390,8 +402,10 @@ namespace AssetStudio.GUI 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), + exportMaterials = Properties.Settings.Default.exportMaterials, + materials = new HashSet(), + uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Populate }), + texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Populate }), }; var convert = animationList != null ? new ModelConverter(gameObject, options, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) @@ -402,6 +416,16 @@ namespace AssetStudio.GUI Logger.Info($"GameObject {gameObject.m_Name} has no mesh, skipping..."); return false; } + if (options.exportMaterials) + { + var materialExportPath = Path.Combine(exportPath, "Materials"); + Directory.CreateDirectory(materialExportPath); + foreach (var material in options.materials) + { + var matItem = new AssetItem(material); + ExportJSONFile(matItem, materialExportPath); + } + } exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx"; ExportFbx(convert, exportPath); return true; @@ -415,12 +439,24 @@ namespace AssetStudio.GUI imageFormat = Properties.Settings.Default.convertType, game = Studio.Game, collectAnimations = Properties.Settings.Default.collectAnimations, + exportMaterials = Properties.Settings.Default.exportMaterials, + materials = new HashSet(), uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs), texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs), }; var convert = animationList != null ? new ModelConverter(rootName, gameObject, options, animationList.Select(x => (AnimationClip)x.Asset).ToArray()) : new ModelConverter(rootName, gameObject, options); + if (options.exportMaterials) + { + var materialExportPath = Path.Combine(exportPath, "Materials"); + Directory.CreateDirectory(materialExportPath); + foreach (var material in options.materials) + { + var matItem = new AssetItem(material); + ExportJSONFile(matItem, materialExportPath); + } + } ExportFbx(convert, exportPath); } diff --git a/AssetStudio.GUI/MainForm.cs b/AssetStudio.GUI/MainForm.cs index 0847454..eb3b897 100644 --- a/AssetStudio.GUI/MainForm.cs +++ b/AssetStudio.GUI/MainForm.cs @@ -136,7 +136,7 @@ namespace AssetStudio.GUI var menuItem = new ToolStripMenuItem(loggerEvent.ToString()) { CheckOnClick = true, Checked = loggerEventType.HasFlag(loggerEvent), Tag = (int)loggerEvent }; loggedEventsMenuItem.DropDownItems.Add(menuItem); } - Logger.Default.Flags = loggerEventType; + Logger.Flags = loggerEventType; Logger.FileLogging = enableFileLogging.Checked; } @@ -1312,6 +1312,8 @@ namespace AssetStudio.GUI imageFormat = Properties.Settings.Default.convertType, game = Studio.Game, collectAnimations = Properties.Settings.Default.collectAnimations, + exportMaterials = false, + materials = new HashSet(), uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs), texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs), }; @@ -1325,6 +1327,8 @@ namespace AssetStudio.GUI imageFormat = Properties.Settings.Default.convertType, game = Studio.Game, collectAnimations = Properties.Settings.Default.collectAnimations, + exportMaterials = false, + materials = new HashSet(), uvs = JsonConvert.DeserializeObject>(Properties.Settings.Default.uvs), texs = JsonConvert.DeserializeObject>(Properties.Settings.Default.texs), }; @@ -2354,7 +2358,7 @@ namespace AssetStudio.GUI Properties.Settings.Default.loggerEventType = loggedEventsMenuItem.DropDownItems.Cast().Select(x => x.Checked ? (int)x.Tag : 0).Sum(); Properties.Settings.Default.Save(); - Logger.Default.Flags = (LoggerEvent)Properties.Settings.Default.loggerEventType; + Logger.Flags = (LoggerEvent)Properties.Settings.Default.loggerEventType; } private void abortStripMenuItem_Click(object sender, EventArgs e) diff --git a/AssetStudio.GUI/Properties/Settings.Designer.cs b/AssetStudio.GUI/Properties/Settings.Designer.cs index 46bc747..de87d79 100644 --- a/AssetStudio.GUI/Properties/Settings.Designer.cs +++ b/AssetStudio.GUI/Properties/Settings.Designer.cs @@ -484,7 +484,7 @@ namespace AssetStudio.GUI.Properties { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("")] + [global::System.Configuration.DefaultSettingValueAttribute("{}")] public string texs { get { return ((string)(this["texs"])); @@ -493,5 +493,17 @@ namespace AssetStudio.GUI.Properties { this["texs"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool exportMaterials { + get { + return ((bool)(this["exportMaterials"])); + } + set { + this["exportMaterials"] = value; + } + } } } diff --git a/AssetStudio.GUI/Properties/Settings.settings b/AssetStudio.GUI/Properties/Settings.settings index af433a5..866cbb7 100644 --- a/AssetStudio.GUI/Properties/Settings.settings +++ b/AssetStudio.GUI/Properties/Settings.settings @@ -117,7 +117,10 @@ {"Animation":{"Item1":true,"Item2":false},"AnimationClip":{"Item1":true,"Item2":true},"Animator":{"Item1":true,"Item2":true},"AnimatorController":{"Item1":true,"Item2":false},"AnimatorOverrideController":{"Item1":true,"Item2":false},"AssetBundle":{"Item1":true,"Item2":false},"AudioClip":{"Item1":true,"Item2":true},"Avatar":{"Item1":true,"Item2":false},"Font":{"Item1":true,"Item2":true},"GameObject":{"Item1":true,"Item2":false},"IndexObject":{"Item1":true,"Item2":false},"Material":{"Item1":true,"Item2":true},"Mesh":{"Item1":true,"Item2":true},"MeshFilter":{"Item1":true,"Item2":false},"MeshRenderer":{"Item1":true,"Item2":false},"MiHoYoBinData":{"Item1":true,"Item2":true},"MonoBehaviour":{"Item1":true,"Item2":true},"MonoScript":{"Item1":true,"Item2":false},"MovieTexture":{"Item1":true,"Item2":true},"PlayerSettings":{"Item1":true,"Item2":false},"RectTransform":{"Item1":true,"Item2":false},"Shader":{"Item1":true,"Item2":true},"SkinnedMeshRenderer":{"Item1":true,"Item2":false},"Sprite":{"Item1":true,"Item2":true},"SpriteAtlas":{"Item1":true,"Item2":false},"TextAsset":{"Item1":true,"Item2":true},"Texture2D":{"Item1":true,"Item2":true},"Transform":{"Item1":true,"Item2":false},"VideoClip":{"Item1":true,"Item2":true},"ResourceManager":{"Item1":true,"Item2":false}} - + {} + + + False \ No newline at end of file diff --git a/AssetStudio.Utility/ModelConverter.cs b/AssetStudio.Utility/ModelConverter.cs index 61c3ba7..d7751eb 100644 --- a/AssetStudio.Utility/ModelConverter.cs +++ b/AssetStudio.Utility/ModelConverter.cs @@ -649,6 +649,10 @@ namespace AssetStudio ImportedMaterial iMat; if (mat != null) { + if (options.exportMaterials) + { + options.materials.Add(mat); + } iMat = ImportedHelpers.FindMaterial(mat.m_Name, MaterialList); if (iMat != null) { @@ -1172,6 +1176,8 @@ namespace AssetStudio public ImageFormat imageFormat; public Game game; public bool collectAnimations; + public bool exportMaterials; + public HashSet materials; public Dictionary uvs; public Dictionary texs; } diff --git a/AssetStudio/ILogger.cs b/AssetStudio/ILogger.cs index 30b8ed3..e034cbc 100644 --- a/AssetStudio/ILogger.cs +++ b/AssetStudio/ILogger.cs @@ -20,27 +20,18 @@ namespace AssetStudio public interface ILogger { - public bool Silent { get; set; } - public LoggerEvent Flags { get; set; } void Log(LoggerEvent loggerEvent, string message); } public sealed class DummyLogger : ILogger { - public bool Silent { get; set; } - public LoggerEvent Flags { get; set; } public void Log(LoggerEvent loggerEvent, string message) { } } public sealed class ConsoleLogger : ILogger { - public bool Silent { get; set; } - public LoggerEvent Flags { get; set; } public void Log(LoggerEvent loggerEvent, string message) { - if (!Flags.HasFlag(loggerEvent) || Silent) - return; - Console.WriteLine("[{0}] {1}", loggerEvent, message); } } @@ -51,9 +42,6 @@ namespace AssetStudio private const string PrevLogFileName = "log_prev.txt"; private readonly object LockWriter = new object(); private StreamWriter Writer; - - public bool Silent { get; set; } - public LoggerEvent Flags { get; set; } public FileLogger() { var logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LogFileName); @@ -71,9 +59,6 @@ namespace AssetStudio } public void Log(LoggerEvent loggerEvent, string message) { - if (!Flags.HasFlag(loggerEvent) || Silent) - return; - lock (LockWriter) { Writer.WriteLine($"[{DateTime.Now}][{loggerEvent}] {message}"); diff --git a/AssetStudio/Logger.cs b/AssetStudio/Logger.cs index e6924a9..bbe9c78 100644 --- a/AssetStudio/Logger.cs +++ b/AssetStudio/Logger.cs @@ -13,11 +13,8 @@ namespace AssetStudio public static ILogger Default = new DummyLogger(); public static ILogger File; - public static bool Silent - { - get => Default.Silent; - set => Default.Silent = value; - } + public static bool Silent { get; set; } + public static LoggerEvent Flags { get; set; } public static bool FileLogging { @@ -48,6 +45,9 @@ namespace AssetStudio public static void Verbose(string message) { + if (!Flags.HasFlag(LoggerEvent.Verbose) || Silent) + return; + try { var callerMethod = new StackTrace().GetFrame(1).GetMethod(); @@ -63,27 +63,42 @@ namespace AssetStudio } public static void Debug(string message) { + if (!Flags.HasFlag(LoggerEvent.Debug) || Silent) + return; + if (FileLogging) File.Log(LoggerEvent.Debug, message); Default.Log(LoggerEvent.Debug, message); } public static void Info(string message) { + if (!Flags.HasFlag(LoggerEvent.Info) || Silent) + return; + if (FileLogging) File.Log(LoggerEvent.Info, message); Default.Log(LoggerEvent.Info, message); } public static void Warning(string message) { + if (!Flags.HasFlag(LoggerEvent.Warning) || Silent) + return; + if (FileLogging) File.Log(LoggerEvent.Warning, message); Default.Log(LoggerEvent.Warning, message); } public static void Error(string message) { + if (!Flags.HasFlag(LoggerEvent.Error) || Silent) + return; + if (FileLogging) File.Log(LoggerEvent.Error, message); Default.Log(LoggerEvent.Error, message); } public static void Error(string message, Exception e) { + if (!Flags.HasFlag(LoggerEvent.Error) || Silent) + return; + var sb = new StringBuilder(); sb.AppendLine(message); sb.AppendLine(e.ToString());