Jelajahi Sumber

Add menu file prop spawning

habeebweeb 4 tahun lalu
induk
melakukan
f80f20cde6

+ 127 - 2
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Constants.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
@@ -13,7 +13,6 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
     internal class Constants
     {
         private static bool beginHandItemInit;
-        private static bool startModItemInit;
         public static readonly string customPosePath;
         public static readonly string scenesPath;
         public static readonly string kankyoPath;
@@ -503,6 +502,132 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             }
         }
 
+        private static void InitializeModProps()
+        {
+            // TODO: cache menu files
+            for (int i = 1; i < MenuFileUtility.MenuCategories.Length; i++)
+            {
+                ModPropDict[MenuCategories[i]] = new List<ModItem>();
+            }
+
+            if (!Configuration.ModItemsOnly)
+            {
+                MenuDataBase menuDatabase = GameMain.Instance.MenuDataBase;
+
+                for (int i = 0; i < menuDatabase.GetDataSize(); i++)
+                {
+                    menuDatabase.SetIndex(i);
+                    ModItem modItem = new ModItem();
+                    if (MenuFileUtility.ParseNativeMenuFile(i, modItem))
+                    {
+                        ModPropDict[modItem.Category].Add(modItem);
+                    }
+                }
+            }
+
+            MenuFileCache cache = new MenuFileCache();
+
+            foreach (string modMenuFile in GameUty.ModOnlysMenuFiles)
+            {
+                ModItem modItem;
+                if (cache.Has(modMenuFile))
+                {
+                    modItem = cache[modMenuFile];
+                }
+                else
+                {
+                    modItem = new ModItem() { MenuFile = modMenuFile, IsMod = true };
+                    MenuFileUtility.ParseMenuFile(modMenuFile, modItem);
+                    cache[modMenuFile] = modItem;
+                }
+                if (MenuFileUtility.ValidBG2MenuFile(modItem)) ModPropDict[modItem.Category].Add(modItem);
+            }
+
+            cache.Serialize();
+
+            foreach (string modFile in Menu.GetModFiles())
+            {
+                ModItem modItem = new ModItem()
+                {
+                    MenuFile = modFile,
+                    IsMod = true,
+                    IsOfficialMod = true,
+                    Priority = 1000f
+                };
+                if (ParseModMenuFile(modFile, modItem))
+                {
+                    ModPropDict[modItem.Category].Add(modItem);
+                }
+            }
+            MenuFilesInitialized = true;
+        }
+
+        public static List<ModItem> GetModPropList(string category)
+        {
+            if (!Configuration.ModItemsOnly)
+            {
+                if (!MenuFileUtility.MenuFilesReady)
+                {
+                    Debug.Log("Menu files are not ready yet");
+                    return null;
+                }
+            }
+
+            if (!MenuFilesInitialized) InitializeModProps();
+
+            if (!ModPropDict.ContainsKey(category)) return null;
+
+            List<ModItem> selectedList = ModPropDict[category];
+
+            if (selectedList[0].Icon == null)
+            {
+                selectedList.Sort((a, b) =>
+                {
+                    int res = a.Priority.CompareTo(b.Priority);
+                    if (res == 0) res = string.Compare(a.Name, b.Name);
+                    return res;
+                });
+
+                string previousMenuFile = String.Empty;
+                selectedList.RemoveAll(item =>
+                {
+                    if (item.Icon == null)
+                    {
+                        Texture2D icon;
+                        string iconFile = item.IconFile;
+                        if (string.IsNullOrEmpty(iconFile) || !GameUty.FileSystem.IsExistentFile(iconFile))
+                        {
+                            Debug.LogWarning($"Could not find icon '{iconFile}' for menu '{item.MenuFile}");
+                            return true;
+                        }
+                        else
+                        {
+                            try
+                            {
+                                icon = ImportCM.CreateTexture(iconFile);
+                            }
+                            catch
+                            {
+                                try
+                                {
+                                    icon = ImportCM.CreateTexture($"tex\\{iconFile}");
+                                }
+                                catch
+                                {
+                                    Debug.LogWarning($"Could not load '{iconFile}' for menu '{item.MenuFile}");
+                                    return true;
+                                }
+                            }
+                        }
+                        item.Icon = icon;
+                    }
+                    return false;
+                });
+            }
+
+            return selectedList;
+        }
+
         private static CsvParser OpenCsvParser(string nei, AFileSystemBase fs)
         {
             try

+ 192 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Panes/BackgroundWindow2Panes/ModPropsPane.cs

@@ -0,0 +1,192 @@
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+namespace COM3D2.MeidoPhotoStudio.Plugin
+{
+    using static MenuFileUtility;
+    internal class ModPropsPane : BasePane
+    {
+        private PropManager propManager;
+        private Dropdown propCategoryDropdown;
+        private Toggle modFilterToggle;
+        private Toggle baseFilterToggle;
+        private Vector2 propListScrollPos;
+        private string SelectedCategory
+        {
+            get => MenuFileUtility.MenuCategories[this.propCategoryDropdown.SelectedItemIndex];
+        }
+        private List<ModItem> modPropList;
+        private string currentCategory;
+        private bool modItemsReady = false;
+        private bool shouldDraw = false;
+        private int categoryIndex = 0;
+        private bool modFilter = false;
+        private bool baseFilter = false;
+        private int currentListCount;
+        private bool isModsOnly = Configuration.ModItemsOnly;
+        private enum FilterType
+        {
+            None, Mod, Base
+        }
+
+        public ModPropsPane(PropManager propManager)
+        {
+            this.propManager = propManager;
+
+            this.modItemsReady = MenuFileUtility.MenuFilesReady || Configuration.ModItemsOnly;
+
+            string[] listItems = Translation.GetArray("clothing", MenuFileUtility.MenuCategories);
+
+            if (!this.modItemsReady)
+            {
+                listItems[0] = Translation.Get("systemMessage", "initializing");
+
+                MenuFileUtility.MenuFilesReadyChange += (s, a) =>
+                {
+                    this.modItemsReady = true;
+                    this.propCategoryDropdown.SetDropdownItems(
+                        Translation.GetArray("clothing", MenuFileUtility.MenuCategories)
+                    );
+                };
+            }
+
+            this.propCategoryDropdown = new Dropdown(listItems);
+
+            this.propCategoryDropdown.SelectionChange += (s, a) =>
+            {
+                if (!this.modItemsReady) return;
+                ChangePropCategory();
+            };
+
+            this.modFilterToggle = new Toggle(Translation.Get("background2Window", "modsToggle"));
+            this.modFilterToggle.ControlEvent += (s, a) => ChangeFilter(FilterType.Mod);
+
+
+            this.baseFilterToggle = new Toggle(Translation.Get("background2Window", "baseToggle"));
+            this.baseFilterToggle.ControlEvent += (s, a) => ChangeFilter(FilterType.Base);
+        }
+
+        protected override void ReloadTranslation()
+        {
+            string[] listItems = Translation.GetArray("clothing", MenuFileUtility.MenuCategories);
+
+            if (!this.modItemsReady) listItems[0] = Translation.Get("systemMessage", "initializing");
+
+            this.propCategoryDropdown.SetDropdownItems(listItems);
+
+
+            this.modFilterToggle.Label = Translation.Get("background2Window", "modsToggle");
+            this.baseFilterToggle.Label = Translation.Get("background2Window", "baseToggle");
+        }
+
+        public override void Draw()
+        {
+            float dropdownButtonHeight = 30f;
+            float dropdownButtonWidth = isModsOnly ? 120f : 90f;
+            GUILayoutOption[] dropdownLayoutOptions = new GUILayoutOption[] {
+                GUILayout.Height(dropdownButtonHeight),
+                GUILayout.Width(dropdownButtonWidth)
+            };
+
+            GUILayout.BeginHorizontal();
+
+            if (isModsOnly)
+            {
+                GUILayout.FlexibleSpace();
+                this.propCategoryDropdown.Draw(dropdownLayoutOptions);
+                GUILayout.FlexibleSpace();
+            }
+            else
+            {
+                GUI.enabled = this.modItemsReady;
+                this.propCategoryDropdown.Draw(dropdownLayoutOptions);
+
+                GUI.enabled = this.shouldDraw;
+                this.modFilterToggle.Draw();
+                this.baseFilterToggle.Draw();
+                GUI.enabled = true;
+            }
+
+            GUILayout.EndHorizontal();
+
+            if (this.shouldDraw)
+            {
+                float windowHeight = Screen.height * 0.7f;
+
+                int buttonSize = 50;
+                int offsetLeft = 15;
+                int offsetTop = 85;
+
+                int columns = 4;
+
+                Rect positionRect = new Rect(offsetLeft, offsetTop + dropdownButtonHeight, 220, windowHeight);
+                Rect viewRect = new Rect(
+                    0, 0, buttonSize * columns, buttonSize * Mathf.Ceil(currentListCount / (float)columns) + 5
+                );
+                propListScrollPos = GUI.BeginScrollView(positionRect, propListScrollPos, viewRect);
+
+                int modIndex = 0;
+                foreach (ModItem modItem in modPropList)
+                {
+                    if ((modFilter && !modItem.IsMod) || (baseFilter && modItem.IsMod)) continue;
+
+                    float x = modIndex % columns * buttonSize;
+                    float y = modIndex / columns * buttonSize;
+                    Rect iconRect = new Rect(x, y, buttonSize, buttonSize);
+                    if (GUI.Button(iconRect, "")) propManager.SpawnModItemProp(modItem);
+                    GUI.DrawTexture(iconRect, modItem.Icon);
+                    modIndex++;
+                }
+
+                GUI.EndScrollView();
+                GUILayout.Space(windowHeight);
+            }
+        }
+
+        private void ChangeFilter(FilterType filterType)
+        {
+            if (this.updating) return;
+
+            if (modFilterToggle.Value && baseFilterToggle.Value)
+            {
+                this.updating = true;
+                modFilterToggle.Value = filterType == FilterType.Mod;
+                baseFilterToggle.Value = filterType == FilterType.Base;
+                this.updating = false;
+            }
+
+            modFilter = modFilterToggle.Value;
+            baseFilter = baseFilterToggle.Value;
+
+            SetListCount();
+        }
+
+        private void ChangePropCategory()
+        {
+            string category = SelectedCategory;
+
+            if (currentCategory == category) return;
+            currentCategory = category;
+
+            categoryIndex = propCategoryDropdown.SelectedItemIndex;
+
+            shouldDraw = categoryIndex > 0;
+
+            if (!shouldDraw) return;
+
+            propListScrollPos = Vector2.zero;
+
+            modPropList = Constants.GetModPropList(category);
+
+            SetListCount();
+        }
+
+        private void SetListCount()
+        {
+            if (modFilter || isModsOnly) currentListCount = modPropList.Count(mod => mod.IsMod);
+            else if (baseFilter) currentListCount = modPropList.Count(mod => !mod.IsMod);
+            else currentListCount = modPropList.Count;
+        }
+    }
+}

+ 3 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Panes/MainWindowPanes/BG2WindowPane.cs

@@ -11,6 +11,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         private PropsPane propsPane;
         private AttachPropPane attachPropPane;
         private MyRoomPropsPane myRoomPropsPane;
+        private ModPropsPane modPropsPane;
         private SelectionGrid propTabs;
         private BasePane currentPropsPane;
 
@@ -22,10 +23,12 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             PropManager propManager = this.environmentManager.PropManager;
             this.propsPane = new PropsPane(propManager);
             this.myRoomPropsPane = new MyRoomPropsPane(propManager);
+            this.modPropsPane = new ModPropsPane(propManager);
             this.attachPropPane = new AttachPropPane(this.meidoManager, propManager);
 
             this.Panes.Add(propsPane);
             this.Panes.Add(myRoomPropsPane);
+            this.Panes.Add(modPropsPane);
 
             this.propTabs = new SelectionGrid(Translation.GetArray("propTabs", new[] { "Props", "MyRoom", "Mod" }));
             this.propTabs.ControlEvent += (s, a) =>

+ 1 - 1
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Windows/BaseWindow.cs

@@ -7,7 +7,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
     internal abstract class BaseWindow : BaseWindowPane
     {
         private static int id = 765;
-        private static int ID { get => id++; }
+        private static int ID => id++;
         public readonly int windowID;
         protected Rect windowRect;
         public abstract Rect WindowRect { get; set; }

+ 8 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Managers/PropManager.cs

@@ -80,6 +80,14 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 ?? new GameObject("Deployment Object Parent");
         }
 
+        public void SpawnModItemProp(MenuFileUtility.ModItem modItem)
+        {
+            GameObject dogu = MenuFileUtility.LoadModel(modItem);
+            string name = modItem.Name;
+            if (dogu != null) AttachDragPoint(dogu, name, new Vector3(0f, 0f, 0.5f));
+            // else Debug.Log($"Could not load mod item prop '{modItem.MenuFile}'");
+        }
+
         public void SpawnMyRoomProp(MenuFileUtility.MyRoomItem item)
         {
             MyRoomCustom.PlacementData.Data data = MyRoomCustom.PlacementData.GetData(item.ID);