Browse Source

Add reinitialization for changes in edit mode

Changing maid body/face/clothing would break drag points, face blends
and gravity transform controls.

By the time the user clicks on a button that changes the maid's
body/face/clothing, a million errors would spit out and breaks
everything. So a patcher that notifies when AllProcPropSeqStart is
called is used.
habeebweeb 4 years ago
parent
commit
38571855c2

+ 4 - 1
COM3D2.MeidoPhotoStudio.Plugin/COM3D2.MeidoPhotoStudio.Plugin.csproj

@@ -26,9 +26,12 @@
         <Reference Include="Ionic.Zlib">
             <HintPath>..\lib\Ionic.Zlib.dll</HintPath>
         </Reference>
-        <Reference Include="BepInEx.dll">
+        <Reference Include="BepInEx">
             <HintPath>..\lib\BepInEx.dll</HintPath>
         </Reference>
+        <Reference Include="0Harmony">
+            <HintPath>..\lib\0Harmony.dll</HintPath>
+        </Reference>
     </ItemGroup>
     <ItemGroup>
         <Content Include="Config\**">

+ 24 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/AllProcPropSeqStartPatcher.cs

@@ -0,0 +1,24 @@
+using System;
+using HarmonyLib;
+
+namespace COM3D2.MeidoPhotoStudio.Plugin
+{
+    // TODO: Extend this further to potentially reduce the need for coroutines that wait for maid proc state
+    internal static class AllProcPropSeqStartPatcher
+    {
+        public static event EventHandler<ProcStartEventArgs> SequenceStart;
+
+        [HarmonyPatch(typeof(Maid), nameof(Maid.AllProcPropSeqStart))]
+        [HarmonyPostfix]
+        private static void NotifyProcStart(Maid __instance)
+        {
+            SequenceStart?.Invoke(null, new ProcStartEventArgs(__instance));
+        }
+    }
+
+    internal class ProcStartEventArgs : EventArgs
+    {
+        public readonly Maid maid;
+        public ProcStartEventArgs(Maid maid) => this.maid = maid;
+    }
+}

+ 1 - 1
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Panes/CallWindowPanes/MaidSelectorPane.cs

@@ -65,7 +65,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                     );
                 }
 
-                GUI.DrawTexture(new Rect(5f, y, buttonHeight, buttonHeight), meido.Portrait);
+                if (meido.Portrait) GUI.DrawTexture(new Rect(5f, y, buttonHeight, buttonHeight), meido.Portrait);
                 GUI.Label(
                     new Rect(95f, y + 30f, buttonWidth - 80f, buttonHeight),
                     $"{meido.LastName}\n{meido.FirstName}", selectedMaid ? labelSelectedStyle : labelStyle

+ 1 - 1
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Panes/OtherPanes/MaidSwitcherPane.cs

@@ -32,7 +32,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 
             PreviousButton.Draw(buttonStyle, GUILayout.Height(40), GUILayout.ExpandWidth(false));
 
-            if (meidoManager.HasActiveMeido)
+            if (meidoManager.HasActiveMeido && meidoManager.ActiveMeido.Portrait)
                 MpsGui.DrawTexture(meidoManager.ActiveMeido.Portrait, GUILayout.Width(70), GUILayout.Height(70));
             else
                 GUILayout.Box("", boxStyle, GUILayout.Height(70), GUILayout.Width(70));

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

@@ -217,6 +217,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 
             HairGravityControl.Move += OnGravityEvent;
             SkirtGravityControl.Move += OnGravityEvent;
+            if (MeidoPhotoStudio.EditMode) AllProcPropSeqStartPatcher.SequenceStart += ReinitializeBody;
 
             IKManager.Initialize();
 
@@ -225,6 +226,55 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             Bone = false;
         }
 
+        private void ReinitializeBody(object sender, ProcStartEventArgs args)
+        {
+            if (Loading || !Body.isLoadedBody) return;
+
+            if (args.maid.status.guid == Maid.status.guid)
+            {
+                MPN[] gravityControlProps = new[] {
+                    MPN.skirt, MPN.onepiece, MPN.mizugi, MPN.panz, MPN.set_maidwear, MPN.set_mywear, MPN.set_underwear,
+                    MPN.hairf, MPN.hairr, MPN.hairs, MPN.hairt
+                };
+
+                // Change body
+                if (Maid.GetProp(MPN.body).boDut)
+                {
+                    IKManager.Destroy();
+                    StartLoad(() =>
+                    {
+                        IKManager.Initialize();
+                        Stop = false;
+                    });
+                }
+                // Change face
+                else if (Maid.GetProp(MPN.head).boDut)
+                {
+                    SetFaceBlendSet(defaultFaceBlendSet);
+                    StartLoad(() =>
+                    {
+                        DefaultEyeRotL = Body.quaDefEyeL;
+                        DefaultEyeRotR = Body.quaDefEyeR;
+                        BackupBlendSetValues();
+                    });
+                }
+                // Gravity control clothing/hair change
+                else if (gravityControlProps.Any(prop => Maid.GetProp(prop).boDut))
+                {
+                    if (HairGravityControl) GameObject.Destroy(HairGravityControl.gameObject);
+                    if (SkirtGravityControl) GameObject.Destroy(SkirtGravityControl.gameObject);
+
+                    StartLoad(() =>
+                    {
+                        InitializeGravityControls();
+                        OnUpdateMeido();
+                    });
+                }
+                // Clothing/accessory changes
+                else StartLoad(() => OnUpdateMeido());
+            }
+        }
+
         public void Unload()
         {
             if (Body.isLoadedBody && Maid.Visible)
@@ -254,6 +304,8 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 SetFaceBlendSet(defaultFaceBlendSet);
             }
 
+            AllProcPropSeqStartPatcher.SequenceStart -= ReinitializeBody;
+
             Body.MuneYureL(1f);
             Body.MuneYureR(1f);
 

+ 1 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/MeidoPhotoStudio.cs

@@ -43,6 +43,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 
         private void Awake()
         {
+            HarmonyLib.Harmony.CreateAndPatchAll(typeof(AllProcPropSeqStartPatcher));
             ScreenshotEvent += OnScreenshotEvent;
             DontDestroyOnLoad(this);
             UnityEngine.SceneManagement.SceneManager.sceneLoaded += OnSceneLoaded;