Browse Source

Add mpn attach props

Stuff like handcuffs and shackles
habeebweeb 4 years ago
parent
commit
f2c3c99305

+ 25 - 0
COM3D2.MeidoPhotoStudio.Plugin/Config/MeidoPhotoStudio/Translations/en/translation.props.json

@@ -1114,6 +1114,30 @@
         "Mrc_PR2carpet02": "Carpet (Brown)",
         "Mrc_gp001fb_Curpet001": "Carpet (Flower)"
     },
+    "mpnAttachPropNames": {
+        "kousokul_ashikasedown_i_.menu": "Ankle Restraints (Below)",
+        "kousokul_ashikasedownout_i_.menu": "Ankle Restraints (Below & Outer)",
+        "kousokul_ashikaseup_i_.menu": "Ankle Restraints (Above)",
+        "kousokul_bar_i_.menu": "Ankle Bar",
+        "kousokul_bathtowel_i_.menu": "Bath Towel",
+        "kousokul_momokaseup_i_.menu": "Ankle and Knee Restraints (Above)",
+        "kousokul_ryouashi_i_.menu": "Leg Restraints",
+        "kousokuu_smroom2_haritsuke_i_.menu": "Crucifixion (SM Room 2)",
+        "kousokuu_smroom2_haritsukemomo_i_.menu": "Crucifixion (SM Room 2) with Restraints",
+        "kousokuu_smroom_haritsuke_i_.menu": "Crucifixion (SM Room)",
+        "kousokuu_smroom_haritsukemomo_i_.menu": "Crucifixion (SM Room) with Restraints",
+        "kousokuu_tekaseone_i_.menu": "Handcuffs with Restraint",
+        "kousokuu_tekaseshort_i_.menu": "Wrist Restraints",
+        "kousokuu_tekasetwo_i_.menu": "Arm Restraints (Above)",
+        "kousokuu_tekasetwodown_i_.menu": "Arm Restraints (Below)",
+        "kousokuu_tsurikawa_i_.menu": "Train Handles (Single)",
+        "kousokuu_tsurikawaback_i_.menu": "Train Handles (Both & Crossed)",
+        "kousokuu_tsurikawafront_i_.menu": "Train Handles (Both)",
+        "kousokuu_ushirode_i_.menu": "Arm Binder",
+        "kousokuu_ushirodeup_i_.menu": "Arm Binder with Arm Restraints",
+        "kousoku_gp002_tejyou_i_.menu": "Handcuffs 2",
+        "kousokuu_tekase_i_.menu": "Handcuffs"
+    },
     "doguCategories": {
         "家具": "Furniture",
         "道具": "Dogu",
@@ -1133,6 +1157,7 @@
         "調理器具": "Kitchenware",
         "敷物": "Rug",
         "other": "Props 1",
+        "mirrors": "Mirrors",
         "mob": "Props 2",
         "desk": "Desk",
         "handItem": "Hand Items",

+ 5 - 0
COM3D2.MeidoPhotoStudio.Plugin/Config/MeidoPhotoStudio/Translations/en/translation.ui.json

@@ -70,6 +70,11 @@
         "x": "Look X",
         "y": "Look Y"
     },
+    "attachMpnPropPane": {
+        "attachButton": "Attach",
+        "detachButton": "Detach",
+        "detachAllButton": "Detach All"
+    },
     "clothing": {
         "noCategory": " --- ",
         "accHat": "Hat",

+ 55 - 6
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Constants.cs

@@ -14,6 +14,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
     internal class Constants
     {
         private static bool beginHandItemInit;
+        private static bool beginMpnAttachInit;
         public const string customPoseDirectory = "Custom Poses";
         public const string customHandDirectory = "Hand Presets";
         public const string sceneDirectory = "Scenes";
@@ -57,9 +58,11 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             = new Dictionary<string, List<ModItem>>(StringComparer.InvariantCultureIgnoreCase);
         public static readonly List<string> SceneDirectoryList = new List<string>();
         public static readonly List<string> KankyoDirectoryList = new List<string>();
+        public static readonly List<MpnAttachProp> MpnAttachPropList = new List<MpnAttachProp>();
         public static int CustomPoseGroupsIndex { get; private set; } = -1;
         public static int MyRoomCustomBGIndex { get; private set; } = -1;
         public static bool HandItemsInitialized { get; private set; } = false;
+        public static bool MpnAttachInitialized { get; private set; } = false;
         public static bool MenuFilesInitialized { get; private set; } = false;
         public static event EventHandler<MenuFilesEventArgs> MenuFilesChange;
         public static event EventHandler<CustomPoseEventArgs> customPoseChange;
@@ -106,6 +109,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             InitializeBGs();
             InitializeDogu();
             InitializeMyRoomProps();
+            InitializeMpnAttachProps();
         }
 
         public static void AddPose(byte[] anmBinary, string filename, string directory)
@@ -627,10 +631,45 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 }
             }
 
-            OnMenuFilesChange(MenuFilesEventArgs.HandItems);
+            OnMenuFilesChange(MenuFilesEventArgs.EventType.HandItems);
             HandItemsInitialized = true;
         }
 
+        private static void InitializeMpnAttachProps()
+        {
+            if (MpnAttachInitialized) return;
+
+            if (!MenuFileUtility.MenuFilesReady)
+            {
+                if (!beginMpnAttachInit) MenuFileUtility.MenuFilesReadyChange += (s, a) => InitializeMpnAttachProps();
+                beginMpnAttachInit = true;
+                return;
+            }
+
+            MenuDataBase menuDataBase = GameMain.Instance.MenuDataBase;
+
+            MPN[] attachMpn = { MPN.kousoku_lower, MPN.kousoku_upper };
+
+            for (int i = 0; i < menuDataBase.GetDataSize(); i++)
+            {
+                menuDataBase.SetIndex(i);
+                MPN itemMpn = (MPN)menuDataBase.GetCategoryMpn();
+
+                if (attachMpn.Any(mpn => mpn == itemMpn))
+                {
+                    string menuFileName = menuDataBase.GetMenuFileName();
+                    string mpnTag = menuDataBase.GetCategoryMpnText();
+
+                    if (menuDataBase.GetBoDelOnly() || menuFileName.EndsWith("_del.menu")) continue;
+
+                    MpnAttachPropList.Add(new MpnAttachProp(itemMpn, menuFileName));
+                }
+            }
+
+            OnMenuFilesChange(MenuFilesEventArgs.EventType.MpnAttach);
+            MpnAttachInitialized = true;
+        }
+
         private static void InitializeMyRoomProps()
         {
             PlacementData.CreateData();
@@ -803,9 +842,9 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             File.WriteAllLines(Path.Combine(configPath, name), list.ToArray());
         }
 
-        private static void OnMenuFilesChange(MenuFilesEventArgs args)
+        private static void OnMenuFilesChange(MenuFilesEventArgs.EventType eventType)
         {
-            MenuFilesChange?.Invoke(null, args);
+            MenuFilesChange?.Invoke(null, new MenuFilesEventArgs(eventType));
         }
 
         private class SerializePoseList
@@ -820,10 +859,8 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         public EventType Type { get; }
         public enum EventType
         {
-            HandItems, MenuFiles
+            HandItems, MenuFiles, MpnAttach
         }
-        public static MenuFilesEventArgs HandItems => new MenuFilesEventArgs(EventType.HandItems);
-        public static MenuFilesEventArgs MenuFiles => new MenuFilesEventArgs(EventType.MenuFiles);
         public MenuFilesEventArgs(EventType type) => this.Type = type;
     }
 
@@ -837,4 +874,16 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             this.Category = category;
         }
     }
+
+    public struct MpnAttachProp
+    {
+        public MPN Tag { get; }
+        public string MenuFile { get; }
+
+        public MpnAttachProp(MPN tag, string menuFile)
+        {
+            this.Tag = tag;
+            this.MenuFile = menuFile;
+        }
+    }
 }

+ 5 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Panes/MainWindowPanes/PoseWindowPane.cs

@@ -13,6 +13,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         private SavePosePane savePosePane;
         private MaidSwitcherPane maidSwitcherPane;
         private MaidFaceLookPane maidFaceLookPane;
+        private MpnAttachPropPane mpnAttachPropPane;
         private MaidDressingPane maidDressingPane;
         private CopyPosePane copyPosePane;
         private HandPresetPane handPresetPane;
@@ -44,6 +45,8 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             this.savePoseToggle = new Toggle(Translation.Get("posePane", "saveToggle"));
             this.savePoseToggle.ControlEvent += (s, a) => savePoseMode = !savePoseMode;
 
+            this.mpnAttachPropPane = new MpnAttachPropPane(this.meidoManager);
+
             this.maidDressingPane = AddPane(new MaidDressingPane(meidoManager));
 
             this.maidIKPane = AddPane(new MaidIKPane(meidoManager));
@@ -89,6 +92,8 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             if (savePoseMode) savePosePane.Draw();
             else maidFaceLookPane.Draw();
 
+            mpnAttachPropPane.Draw();
+
             maidDressingPane.Draw();
 
             MiscGUI.WhiteLine();

+ 104 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Panes/PoseWindowPanes/MpnAttachPropPane.cs

@@ -0,0 +1,104 @@
+using System.Linq;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace COM3D2.MeidoPhotoStudio.Plugin
+{
+    internal class MpnAttachPropPane : BasePane
+    {
+        private MeidoManager meidoManager;
+        private Dropdown mpnAttachDropdown;
+        private Button previousPropButton;
+        private Button nextPropButton;
+        private Button attachPropButton;
+        private Button detachPropButton;
+        private Button detachAllButton;
+
+        public MpnAttachPropPane(MeidoManager meidoManager)
+        {
+            this.meidoManager = meidoManager;
+
+            this.mpnAttachDropdown = new Dropdown(new[] { string.Empty });
+
+            if (!Constants.MpnAttachInitialized) Constants.MenuFilesChange += InitializeMpnAttach;
+
+            SetDropdownList(!Constants.MpnAttachInitialized);
+
+            this.previousPropButton = new Button("<");
+            this.previousPropButton.ControlEvent += (s, a) => this.mpnAttachDropdown.Step(-1);
+
+            this.nextPropButton = new Button(">");
+            this.nextPropButton.ControlEvent += (s, a) => this.mpnAttachDropdown.Step(1);
+
+            this.attachPropButton = new Button(Translation.Get("attachMpnPropPane", "attachButton"));
+            this.attachPropButton.ControlEvent += (s, a) => AttachProp();
+
+            this.detachPropButton = new Button(Translation.Get("attachMpnPropPane", "detachButton"));
+            this.detachPropButton.ControlEvent += (s, a) => AttachProp(detach: true);
+
+            this.detachAllButton = new Button(Translation.Get("attachMpnPropPane", "detachAllButton"));
+            this.detachAllButton.ControlEvent += (s, a) => DetachAll();
+        }
+
+        protected override void ReloadTranslation()
+        {
+            this.attachPropButton.Label = Translation.Get("attachMpnPropPane", "attachButton");
+            this.detachPropButton.Label = Translation.Get("attachMpnPropPane", "detachButton");
+            this.detachAllButton.Label = Translation.Get("attachMpnPropPane", "detachAllButton");
+            SetDropdownList();
+        }
+
+        public override void Draw()
+        {
+            GUI.enabled = this.meidoManager.HasActiveMeido && Constants.MpnAttachInitialized;
+
+            GUILayoutOption noExpand = GUILayout.ExpandWidth(false);
+
+            GUILayout.BeginHorizontal();
+            this.previousPropButton.Draw(noExpand);
+            this.mpnAttachDropdown.Draw(GUILayout.Width(153f));
+            this.nextPropButton.Draw(noExpand);
+            GUILayout.EndHorizontal();
+
+            GUILayout.BeginHorizontal();
+            this.attachPropButton.Draw();
+            this.detachPropButton.Draw();
+            GUILayout.EndHorizontal();
+            this.detachAllButton.Draw();
+
+            GUI.enabled = true;
+        }
+
+        private void InitializeMpnAttach(object sender, MenuFilesEventArgs args)
+        {
+            if (args.Type == MenuFilesEventArgs.EventType.MpnAttach) SetDropdownList();
+        }
+
+        private void SetDropdownList(bool initializing = false)
+        {
+            IEnumerable<string> dropdownList = initializing
+                ? new[] { Translation.Get("systemMessage", "initializing") }
+                : Translation.GetArray(
+                    "mpnAttachPropNames", Constants.MpnAttachPropList.Select(mpnProp => mpnProp.MenuFile)
+                );
+
+            this.mpnAttachDropdown.SetDropdownItems(dropdownList.ToArray());
+        }
+
+        private void AttachProp(bool detach = false)
+        {
+            if (!this.meidoManager.HasActiveMeido) return;
+
+            MpnAttachProp prop = Constants.MpnAttachPropList[this.mpnAttachDropdown.SelectedItemIndex];
+
+            this.meidoManager.ActiveMeido.SetMpnProp(prop, detach);
+        }
+
+        private void DetachAll()
+        {
+            if (!this.meidoManager.HasActiveMeido) return;
+
+            this.meidoManager.ActiveMeido.DetachAllMpnAttach();
+        }
+    }
+}

+ 45 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Meido/Meido.cs

@@ -154,6 +154,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         {
             if (Body.isLoadedBody)
             {
+                DetachAllMpnAttach();
                 Body.jbMuneL.enabled = true;
                 Body.jbMuneR.enabled = true;
             }
@@ -343,6 +344,20 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             Maid.AllProcProp();
         }
 
+        public void SetMpnProp(MpnAttachProp prop, bool detach)
+        {
+            if (detach) Maid.ResetProp(prop.Tag, false);
+            else Maid.SetProp(prop.Tag, prop.MenuFile, 0, true);
+            Maid.AllProcProp();
+        }
+
+        public void DetachAllMpnAttach(bool unload = false)
+        {
+            Maid.ResetProp(MPN.kousoku_lower, false);
+            Maid.ResetProp(MPN.kousoku_upper, false);
+            Maid.AllProcProp();
+        }
+
         private CacheBoneDataArray GetCacheBoneData()
         {
             CacheBoneDataArray cache = this.Maid.gameObject.GetComponent<CacheBoneDataArray>();
@@ -433,6 +448,14 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 tempWriter.Write(CurlingBack);
                 tempWriter.Write(PantsuShift);
 
+                bool hasKousokuUpper = Body.GetSlotLoaded(SlotID.kousoku_upper);
+                tempWriter.Write(hasKousokuUpper);
+                if (hasKousokuUpper) tempWriter.Write(Maid.GetProp(MPN.kousoku_upper).strTempFileName);
+
+                bool hasKousokuLower = Body.GetSlotLoaded(SlotID.kousoku_lower);
+                tempWriter.Write(hasKousokuLower);
+                if (hasKousokuLower) tempWriter.Write(Maid.GetProp(MPN.kousoku_lower).strTempFileName);
+
                 binaryWriter.Write(memoryStream.Length);
                 binaryWriter.Write(memoryStream.ToArray());
             }
@@ -475,6 +498,8 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         public void Deserialize(BinaryReader binaryReader, int dataVersion, bool mmScene)
         {
             Maid.GetAnimation().Stop();
+            DetachAllMpnAttach();
+
             binaryReader.ReadInt64(); // meido buffer length
             // transform
             Maid.transform.position = binaryReader.ReadVector3();
@@ -526,6 +551,26 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             if (CurlingFront != curlingFront) SetCurling(Curl.front, curlingFront);
             if (CurlingBack != curlingBack) SetCurling(Curl.back, curlingBack);
             SetCurling(Curl.shift, binaryReader.ReadBoolean());
+
+            bool hasKousokuUpper = binaryReader.ReadBoolean();
+            if (hasKousokuUpper)
+            {
+                try
+                {
+                    SetMpnProp(new MpnAttachProp(MPN.kousoku_upper, binaryReader.ReadString()), false);
+                }
+                catch { }
+            }
+
+            bool hasKousokuLower = binaryReader.ReadBoolean();
+            if (hasKousokuLower)
+            {
+                try
+                {
+                    SetMpnProp(new MpnAttachProp(MPN.kousoku_lower, binaryReader.ReadString()), false);
+                }
+                catch { }
+            }
             // OnUpdateMeido();
         }