瀏覽代碼

Add parsing regular menu files

Thought it wasn't needed but remembered that COM3D2 does not add meu
files in the Mod folder to the MenuDataBase

Also changed ModItem.Priority to a float since menu file priority is not
stored as an int
habeebweeb 4 年之前
父節點
當前提交
b232ae61b3
共有 1 個文件被更改,包括 129 次插入39 次删除
  1. 129 39
      COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/MenuFileUtility.cs

+ 129 - 39
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/MenuFileUtility.cs

@@ -3,6 +3,7 @@ using System.Text;
 using System.IO;
 using System.Collections;
 using System.Collections.Generic;
+using System.Linq;
 using UnityEngine;
 using UnityEngine.Rendering;
 
@@ -10,12 +11,13 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 {
     internal static class MenuFileUtility
     {
-        private static readonly HashSet<string> accMpn = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase)
-        {
-            "accashi", "acchana", "acchat", "acchead", "accheso", "acckami", "acckamisub", "acckubi", "acckubiwa",
-            "accmimi", "accnip", "accsenaka", "accshippo", "accude", "accxxx", "bra", "glove", "headset", "megane",
-            "mizugi", "onepiece", "panz", "shoes", "skirt", "stkg", "wear",
+        public const string noCategory = "noCategory";
+        public static string[] MenuCategories = new[] {
+            noCategory, "acchat", "headset", "wear", "skirt", "onepiece", "mizugi", "bra", "panz", "stkg", "shoes",
+            "acckami", "megane", "acchead", "acchana", "accmimi", "glove", "acckubi", "acckubiwa", "acckamisub",
+            "accnip", "accude", "accheso", "accashi", "accsenaka", "accshippo", "accxxx"
         };
+        private static readonly HashSet<string> accMpn = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
         private enum IMode
         {
             None, ItemChange, TexChange
@@ -25,6 +27,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 
         static MenuFileUtility()
         {
+            accMpn.UnionWith(MenuCategories.Skip(1));
             GameMain.Instance.StartCoroutine(CheckMenuDataBaseJob());
         }
 
@@ -55,7 +58,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 string menuPropString = String.Empty;
                 string menuPropStringTemp = String.Empty;
                 // string tempString3 = String.Empty;
-                string slotName = String.Empty;
+                // string slotName = String.Empty;
 
                 try
                 {
@@ -453,17 +456,17 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 
         public static GameObject LoadModel(string menuFile)
         {
-            return LoadModel(new ItemData { MenuFile = menuFile });
+            return LoadModel(new ModItem { MenuFile = menuFile });
         }
 
-        public static GameObject LoadModel(ItemData menuItem)
+        public static GameObject LoadModel(ModItem modItem)
         {
             byte[] menuBuffer = null;
             byte[] modMenuBuffer = null;
 
-            if (menuItem.IsOfficialMod)
+            if (modItem.IsOfficialMod)
             {
-                using (FileStream fileStream = new FileStream(menuItem.MenuFile, FileMode.Open))
+                using (FileStream fileStream = new FileStream(modItem.MenuFile, FileMode.Open))
                 {
                     if (fileStream == null || fileStream.Length == 0)
                     {
@@ -478,7 +481,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 }
             }
 
-            string menu = menuItem.IsOfficialMod ? menuItem.BaseMenuFile : menuItem.MenuFile;
+            string menu = modItem.IsOfficialMod ? modItem.BaseMenuFile : modItem.MenuFile;
 
             using (AFileBase afileBase = GameUty.FileOpen(menu))
             {
@@ -510,27 +513,28 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 }
                 catch
                 {
-                    Debug.LogError($"Could not load mesh for '{menuItem.MenuFile}'");
+                    Debug.LogError($"Could not load mesh for '{modItem.MenuFile}'");
                 }
 
                 if (gameObject != null)
                 {
                     foreach (MaterialChange matChange in modelInfo.MaterialChanges)
                     {
-                        foreach (Transform transform in gameObject.transform.GetComponentInChildren<Transform>(true))
+                        foreach (Transform transform in gameObject.transform.GetComponentsInChildren<Transform>(true))
                         {
                             Renderer renderer = transform.GetComponent<Renderer>();
                             if (renderer != null && renderer.material != null
                                 && matChange.MaterialIndex < renderer.materials.Length
                             )
                             {
-                                renderer.materials[matChange.MaterialIndex] =
-                                    ImportCM.LoadMaterial(matChange.MaterialFile, null);
+                                renderer.materials[matChange.MaterialIndex] = ImportCM.LoadMaterial(
+                                        matChange.MaterialFile, null, renderer.materials[matChange.MaterialIndex]
+                                    );
                             }
                         }
                     }
 
-                    if (menuItem.IsOfficialMod)
+                    if (modItem.IsOfficialMod)
                     {
                         ProcModScriptBin(modMenuBuffer, gameObject);
                     }
@@ -540,27 +544,113 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             }
             else
             {
-                Debug.LogWarning($"Could not parse menu file '{menuItem.MenuFile}'");
+                Debug.LogWarning($"Could not parse menu file '{modItem.MenuFile}'");
                 return null;
             }
         }
 
-        public static bool ParseNativeMenuFile(int menuIndex, ItemData menuItem)
+        public static bool ParseNativeMenuFile(int menuIndex, ModItem modItem)
         {
             MenuDataBase menuDataBase = GameMain.Instance.MenuDataBase;
             menuDataBase.SetIndex(menuIndex);
             if (menuDataBase.GetBoDelOnly()) return false;
-            menuItem.Category = menuDataBase.GetCategoryMpnText();
-            if (!accMpn.Contains(menuItem.Category)) return false;
-            menuItem.MenuFile = menuDataBase.GetMenuFileName().ToLower();
-            if (!validBG2MenuFile(menuItem.MenuFile)) return false;
-            menuItem.Name = menuDataBase.GetMenuName();
-            menuItem.IconFile = menuDataBase.GetIconS();
-            menuItem.Priority = (int)menuDataBase.GetPriority();
+            modItem.Category = menuDataBase.GetCategoryMpnText();
+            if (!accMpn.Contains(modItem.Category)) return false;
+            modItem.MenuFile = menuDataBase.GetMenuFileName().ToLower();
+            if (!validBG2MenuFile(modItem.MenuFile)) return false;
+            modItem.Name = menuDataBase.GetMenuName();
+            modItem.IconFile = menuDataBase.GetIconS();
+            modItem.Priority = menuDataBase.GetPriority();
             return true;
         }
 
-        public static bool ParseModMenuFile(string modMenuFile, ItemData menuItem)
+        public static bool ParseMenuFile(string menuFile, ModItem modItem)
+        {
+            if (!validBG2MenuFile(menuFile)) return false;
+
+            byte[] buf = null;
+            try
+            {
+                using (AFileBase afileBase = GameUty.FileOpen(menuFile))
+                {
+                    if (afileBase == null || !afileBase.IsValid() || afileBase.GetSize() == 0) return false;
+                    buf = afileBase.ReadAll();
+                }
+            }
+            catch
+            {
+                Debug.LogError($"Could not read menu file '{menuFile}'");
+                return false;
+            }
+
+            using (BinaryReader binaryReader = new BinaryReader(new MemoryStream(buf), Encoding.UTF8))
+            {
+                string menuHeader = binaryReader.ReadString();
+                NDebug.Assert(
+                    menuHeader == "CM3D2_MENU", "ProcScriptBin 例外 : ヘッダーファイルが不正です。" + menuHeader
+                );
+                binaryReader.ReadInt32(); // file version
+                binaryReader.ReadString(); // txt path
+                modItem.Name = binaryReader.ReadString(); // name
+                modItem.Category = binaryReader.ReadString(); // category
+                if (!accMpn.Contains(modItem.Category)) return false;
+                binaryReader.ReadString(); // description
+                binaryReader.ReadInt32(); // idk (as long)
+
+                string menuPropString = String.Empty;
+                string menuPropStringTemp = String.Empty;
+
+                try
+                {
+                    while (true)
+                    {
+                        int numberOfProps = (int)binaryReader.ReadByte();
+                        menuPropStringTemp = menuPropString;
+                        menuPropString = String.Empty;
+
+                        if (numberOfProps != 0)
+                        {
+                            for (int i = 0; i < numberOfProps; i++)
+                            {
+                                menuPropString = $"{menuPropString}\"{binaryReader.ReadString()}\"";
+                            }
+
+                            if (menuPropString != string.Empty)
+                            {
+                                string header = UTY.GetStringCom(menuPropString);
+                                string[] menuProps = UTY.GetStringList(menuPropString);
+
+                                if (header == "end")
+                                {
+                                    break;
+                                }
+                                else if (header == "icons" || header == "icon")
+                                {
+                                    modItem.IconFile = menuProps[1];
+                                    break;
+                                }
+                                else if (header == "priority")
+                                {
+                                    modItem.Priority = float.Parse(menuProps[1]);
+                                }
+                            }
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+                }
+                catch (Exception e)
+                {
+                    Debug.LogWarning($"Could not parse menu file '{menuFile}' because {e.Message}");
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static bool ParseModMenuFile(string modMenuFile, ModItem modItem)
         {
             if (!validBG2MenuFile(modMenuFile)) return false;
 
@@ -579,9 +669,9 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                     fileStream.Read(buf, 0, (int)fileStream.Length);
                 }
             }
-            catch
+            catch (Exception e)
             {
-                Debug.LogError($"Could not read mod menu file '{modMenuFile}'");
+                Debug.LogError($"Could not read mod menu file '{modMenuFile} because {e.Message}'");
                 return false;
             }
 
@@ -597,10 +687,10 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                         binaryReader.ReadInt32();
                         string iconName = binaryReader.ReadString();
                         string baseItemPath = binaryReader.ReadString().Replace(":", " ");
-                        menuItem.BaseMenuFile = Path.GetFileName(baseItemPath);
-                        menuItem.Name = binaryReader.ReadString();
-                        menuItem.Category = binaryReader.ReadString();
-                        if (!accMpn.Contains(menuItem.Category)) return false;
+                        modItem.BaseMenuFile = Path.GetFileName(baseItemPath);
+                        modItem.Name = binaryReader.ReadString();
+                        modItem.Category = binaryReader.ReadString();
+                        if (!accMpn.Contains(modItem.Category)) return false;
                         binaryReader.ReadString();
                         string mpnValue = binaryReader.ReadString();
                         MPN mpn = MPN.null_mpn;
@@ -627,15 +717,15 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                             {
                                 Texture2D tex = new Texture2D(1, 1, TextureFormat.RGBA32, false);
                                 tex.LoadImage(data);
-                                menuItem.Icon = tex;
+                                modItem.Icon = tex;
                                 break;
                             }
                         }
                     }
                 }
-                catch
+                catch (Exception e)
                 {
-                    Debug.LogWarning($"Could not parse mod menu file '{modMenuFile}'");
+                    Debug.LogWarning($"Could not parse mod menu file '{modMenuFile}' because {e}");
                     return false;
                 }
             }
@@ -646,7 +736,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         {
             menu = Path.GetFileNameWithoutExtension(menu).ToLower();
             return !(menu.EndsWith("_del") || menu.Contains("zurashi") || menu.Contains("mekure")
-                || menu.Contains("porori") || menu.Contains("moza"));
+                || menu.Contains("porori") || menu.Contains("moza") || menu.Contains("folder"));
         }
 
         public abstract class MenuItem
@@ -655,19 +745,19 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             public Texture2D Icon { get; set; }
         }
 
-        public class ItemData : MenuItem
+        public class ModItem : MenuItem
         {
             public string MenuFile { get; set; }
             public string BaseMenuFile { get; set; }
             public string Name { get; set; }
             public string Category { get; set; }
-            public int Priority { get; set; }
+            public float Priority { get; set; }
             public bool IsMod { get; set; }
             public bool IsOfficialMod { get; set; }
             public string ModelFile { get; set; }
         }
 
-        public class CreativeItem : MenuItem
+        public class MyRoomItem : MenuItem
         {
             public int ID { get; set; }
             public string PrefabName { get; set; }