Browse Source

Add IK toggle pane

habeebweeb 4 years ago
parent
commit
720b025c47

+ 0 - 1
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Controls/Slider.cs

@@ -39,7 +39,6 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         public Slider(float min, float max, float value = 0) : this("", min, max, value) { }
         public override void Draw(params GUILayoutOption[] layoutOptions)
         {
-
             if (!Visible) return;
             GUIStyle sliderStyle = new GUIStyle(GUI.skin.horizontalSlider);
             if (hasLabel)

+ 68 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Panes/PoseWindowPanes/MaidIKPane.cs

@@ -0,0 +1,68 @@
+using UnityEngine;
+
+namespace COM3D2.MeidoPhotoStudio.Plugin
+{
+    public class MaidIKPane : BasePane
+    {
+        private MeidoManager meidoManager;
+        private Toggle ikToggle;
+        private Toggle releaseIKToggle;
+        private Toggle boneIKToggle;
+        private enum IKToggle
+        {
+            IK, Release, Bone
+        }
+
+        public MaidIKPane(MeidoManager meidoManager)
+        {
+            this.meidoManager = meidoManager;
+            this.meidoManager.AnimeChange += (s, a) =>
+            {
+                if (!this.meidoManager.HasActiveMeido) return;
+                if (TabsPane.SelectedTab == Constants.Window.Pose) Update();
+            };
+
+            this.ikToggle = new Toggle(Translation.Get("maidPoseWindow", "ikToggle"), true);
+            this.ikToggle.ControlEvent += (s, a) => SetIK(IKToggle.IK, this.ikToggle.Value);
+
+            this.releaseIKToggle = new Toggle(Translation.Get("maidPoseWindow", "releaseToggle"));
+            this.releaseIKToggle.ControlEvent += (s, a) => SetIK(IKToggle.Release, this.releaseIKToggle.Value);
+
+            this.boneIKToggle = new Toggle(Translation.Get("maidPoseWindow", "boneToggle"));
+            this.boneIKToggle.ControlEvent += (s, a) => SetIK(IKToggle.Bone, this.boneIKToggle.Value);
+        }
+
+        private void SetIK(IKToggle toggle, bool value)
+        {
+            if (updating) return;
+            if (toggle == IKToggle.IK) this.meidoManager.ActiveMeido.SetIKActive(value);
+            else if (toggle == IKToggle.Release) this.meidoManager.ActiveMeido.IKRelease();
+            else if (toggle == IKToggle.Bone) this.meidoManager.ActiveMeido.IsBone = value;
+        }
+
+        public override void Update()
+        {
+            this.updating = true;
+            this.ikToggle.Value = this.meidoManager.ActiveMeido.IsIK;
+            this.releaseIKToggle.Value = this.meidoManager.ActiveMeido.IsStop;
+            this.boneIKToggle.Value = this.meidoManager.ActiveMeido.IsBone;
+            this.updating = false;
+        }
+
+        public override void Draw(params GUILayoutOption[] layoutOptions)
+        {
+            bool active = this.meidoManager.HasActiveMeido;
+
+            GUILayout.BeginHorizontal();
+            GUI.enabled = active;
+            this.ikToggle.Draw();
+
+            GUI.enabled = active ? this.meidoManager.ActiveMeido.IsStop : false;
+            this.releaseIKToggle.Draw();
+
+            GUI.enabled = active ? this.ikToggle.Value : false;
+            this.boneIKToggle.Draw();
+            GUILayout.EndHorizontal();
+        }
+    }
+}

+ 22 - 2
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Panes/PoseWindowPanes/MaidPoseSelectorPane.cs

@@ -66,13 +66,33 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         private void ChangePose(object sender, EventArgs args)
         {
             selectedPose = poseDropdown.SelectedItemIndex;
+
+            if (updating) return;
+            PoseInfo poseInfo = MakePoseInfo();
+            meidoManager.ActiveMeido.SetPose(poseInfo);
+        }
+
+        private PoseInfo MakePoseInfo()
+        {
+            int poseGroup = this.poseGroupDropdown.SelectedItemIndex;
+            int pose = this.poseDropdown.SelectedItemIndex;
+
             string poseName;
             if (this.poseGroupDropdown.SelectedItemIndex >= Constants.CustomPoseGroupsIndex)
                 poseName = Constants.CustomPoseDict[selectedPoseGroup][selectedPose].Value;
             else
                 poseName = Constants.PoseDict[selectedPoseGroup][selectedPose];
 
-            meidoManager.ActiveMeido.SetPose(poseName);
+            return new PoseInfo(poseGroup, pose, poseName);
+        }
+
+        public override void Update()
+        {
+            this.updating = true;
+            PoseInfo poseInfo = this.meidoManager.ActiveMeido.poseInfo;
+            this.poseGroupDropdown.SelectedItemIndex = poseInfo.PoseGroupIndex;
+            this.poseDropdown.SelectedItemIndex = poseInfo.PoseIndex;
+            this.updating = false;
         }
 
         public override void Draw(params GUILayoutOption[] layoutOptions)
@@ -90,7 +110,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 GUILayout.Width(dropdownButtonWidth)
             };
 
-            GUI.enabled = meidoManager.HasActiveMeido;
+            GUI.enabled = meidoManager.HasActiveMeido && !meidoManager.ActiveMeido.IsStop;
 
             GUILayout.BeginHorizontal();
             this.poseGroupLeftButton.Draw(arrowLayoutOptions);

+ 14 - 4
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Windows/MainWindows/MaidPoseWindow.cs

@@ -9,21 +9,24 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
     public class MaidPoseWindow : BaseMainWindow
     {
         private MeidoManager meidoManager;
-        private MaidPoseSelectorPane poseSelectorPane;
+        private MaidPoseSelectorPane maidPosePane;
         private MaidFaceLookPane maidFaceLookPane;
         private MaidDressingPane maidDressingPane;
+        private MaidIKPane maidIKPane;
         private Toggle freeLookToggle;
         public MaidPoseWindow(MeidoManager meidoManager)
         {
             this.meidoManager = meidoManager;
             this.meidoManager.SelectMeido += OnMeidoSelect;
 
-            this.poseSelectorPane = new MaidPoseSelectorPane(meidoManager);
+            this.maidPosePane = new MaidPoseSelectorPane(meidoManager);
             this.maidFaceLookPane = new MaidFaceLookPane(meidoManager);
             this.maidFaceLookPane.Enabled = false;
 
             this.maidDressingPane = new MaidDressingPane(meidoManager);
 
+            this.maidIKPane = new MaidIKPane(meidoManager);
+
             TabsPane.TabChange += OnTabChange;
 
             this.freeLookToggle = new Toggle(Translation.Get("freeLook", "freeLookToggle"), false);
@@ -44,9 +47,9 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         public override void Draw(params GUILayoutOption[] layoutOptions)
         {
             MaidSwitcherPane.Draw();
-            poseSelectorPane.Draw();
+            maidPosePane.Draw();
 
-            GUILayout.BeginScrollView(this.scrollPos);
+            this.scrollPos = GUILayout.BeginScrollView(this.scrollPos);
 
             GUILayout.BeginHorizontal();
             GUI.enabled = this.meidoManager.HasActiveMeido;
@@ -56,6 +59,11 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             maidFaceLookPane.Draw();
 
             maidDressingPane.Draw();
+
+            MiscGUI.WhiteLine();
+
+            maidIKPane.Draw();
+
             GUILayout.EndScrollView();
         }
 
@@ -65,8 +73,10 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 
             if (TabsPane.SelectedTab == Constants.Window.Pose)
             {
+                maidPosePane.Update();
                 maidFaceLookPane.Update();
                 maidDressingPane.Update();
+                maidIKPane.Update();
             }
         }
 

+ 98 - 39
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Managers/DragPointManager.cs

@@ -87,6 +87,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         private IKMode ikModeOld = IKMode.None;
         public event EventHandler<MeidoChangeEventArgs> SelectMaid;
         public bool Initialized { get; private set; }
+        public bool Active { get; set; }
         public DragPointManager(Meido meido)
         {
             meido.BodyLoad += Initialize;
@@ -98,6 +99,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         {
             if (Initialized) return;
 
+            this.Active = true;
             InitializeBones();
             InitializeDragPoints();
             Initialized = true;
@@ -113,10 +115,12 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             DragPoint = null;
             BoneTransform = null;
             Initialized = false;
+            this.Active = false;
         }
 
         public void Deactivate()
         {
+            this.Active = false;
             foreach (KeyValuePair<Bone, GameObject> dragPoint in DragPoint)
             {
                 dragPoint.Value.SetActive(false);
@@ -125,6 +129,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 
         public void Activate()
         {
+            this.Active = true;
             ikMode = ikModeOld = IKMode.None;
             UpdateIK();
         }
@@ -171,11 +176,36 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 
         private void UpdateIK()
         {
-            Deactivate();
+            if (Active)
+            {
+                foreach (KeyValuePair<Bone, GameObject> dragPoint in DragPoint)
+                {
+                    dragPoint.Value.SetActive(false);
+                }
 
-            foreach (Bone bone in IKGroup[ikMode])
+                foreach (Bone bone in IKGroup[ikMode])
+                {
+                    DragPoint[bone].SetActive(true);
+                }
+            }
+            else
             {
-                DragPoint[bone].SetActive(true);
+                if (ikMode == IKMode.BodySelect)
+                {
+                    DragPoint[Bone.Body].SetActive(true);
+                    DragPoint[Bone.Head].SetActive(true);
+                }
+                else if (ikMode == IKMode.BodyTransform)
+                {
+                    DragPoint[Bone.Body].SetActive(true);
+                    DragPoint[Bone.Cube].SetActive(true);
+                }
+                else
+                {
+                    DragPoint[Bone.Body].SetActive(false);
+                    DragPoint[Bone.Head].SetActive(false);
+                    DragPoint[Bone.Cube].SetActive(false);
+                }
             }
         }
 
@@ -216,13 +246,17 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 
                 DragJointForearm dragUpper = dragPoints[0].AddComponent<DragJointForearm>();
                 dragUpper.Initialize(upper, false, maid, () => upper[2].position, () => Vector3.zero);
+                dragUpper.DragEvent += OnDragEvent;
                 DragJointForearm dragMiddle = dragPoints[1].AddComponent<DragJointForearm>();
                 dragMiddle.Initialize(middle, leg, maid, () => middle[2].position, () => Vector3.zero);
+                dragMiddle.DragEvent += OnDragEvent;
                 DragJointHand dragLower = dragPoints[2].AddComponent<DragJointHand>();
                 dragLower.Initialize(lower, leg, maid, () => lower[2].position, () => Vector3.zero);
+                dragLower.DragEvent += OnDragEvent;
                 return dragPoints;
             };
 
+            // Cube Dragpoint
             DragPoint[Bone.Cube] = MakeDragPoint(PrimitiveType.Cube, new Vector3(0.12f, 0.12f, 0.12f), transparentBlue2);
 
             DragPoint[Bone.Cube].AddComponent<DragBody>()
@@ -231,6 +265,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                     () => maid.transform.eulerAngles
                 );
 
+            // Body Dragpoint
             DragPoint[Bone.Body] = MakeDragPoint(PrimitiveType.Capsule, new Vector3(0.2f, 0.3f, 0.24f), transparentBlue);
 
             DragBody dragBody = DragPoint[Bone.Body].AddComponent<DragBody>();
@@ -248,6 +283,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             );
             dragBody.Select += (s, e) => OnMeidoSelect(new MeidoChangeEventArgs(meido.ActiveSlot, true));
 
+            // Head Dragpoint
             DragPoint[Bone.Head] = MakeDragPoint(PrimitiveType.Sphere, new Vector3(0.2f, 0.24f, 0.2f), transparentBlue);
             DragHead dragHead = DragPoint[Bone.Head].AddComponent<DragHead>();
             dragHead.Initialize(BoneTransform[Bone.Neck], maid,
@@ -259,7 +295,9 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 () => new Vector3(BoneTransform[Bone.Head].eulerAngles.x, BoneTransform[Bone.Head].eulerAngles.y, BoneTransform[Bone.Head].eulerAngles.z + 90f)
             );
             dragHead.Select += (s, a) => OnMeidoSelect(new MeidoChangeEventArgs(meido.ActiveSlot, true, false));
+            dragHead.DragEvent += OnDragEvent;
 
+            // Torso Dragpoint
             DragPoint[Bone.Torso] = MakeDragPoint(PrimitiveType.Capsule, new Vector3(0.2f, 0.19f, 0.24f), transparentBlue);
             Transform spineTrans1 = BoneTransform[Bone.Spine1];
             Transform spineTrans2 = BoneTransform[Bone.Spine1a];
@@ -269,37 +307,41 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 BoneTransform[Bone.Spine0a],
                 BoneTransform[Bone.Spine]
             };
-            DragPoint[Bone.Torso].AddComponent<DragTorso>()
-                .Initialize(maid, spineParts,
-                    () => new Vector3(
-                        spineTrans1.position.x,
-                        (spineTrans2.position.y * 2f) / 2f,
-                        spineTrans1.position.z
-                    ),
-                    () => new Vector3(
-                        spineTrans1.eulerAngles.x,
-                        spineTrans1.eulerAngles.y,
-                        spineTrans1.eulerAngles.z + 90f
-                    )
-                );
+            DragTorso dragTorso = DragPoint[Bone.Torso].AddComponent<DragTorso>();
+            dragTorso.Initialize(maid, spineParts,
+                () => new Vector3(
+                    spineTrans1.position.x,
+                    (spineTrans2.position.y * 2f) / 2f,
+                    spineTrans1.position.z
+                ),
+                () => new Vector3(
+                    spineTrans1.eulerAngles.x,
+                    spineTrans1.eulerAngles.y,
+                    spineTrans1.eulerAngles.z + 90f
+                )
+            );
+            dragTorso.DragEvent += OnDragEvent;
 
+            // Pelvis Dragpoint
             DragPoint[Bone.Pelvis] = MakeDragPoint(PrimitiveType.Capsule, new Vector3(0.2f, 0.15f, 0.24f), transparentBlue);
             Transform pelvisTrans = BoneTransform[Bone.Pelvis];
             Transform spineTrans = BoneTransform[Bone.Spine];
-            DragPoint[Bone.Pelvis].AddComponent<DragPelvis>()
-                .Initialize(maid, BoneTransform[Bone.Pelvis],
-                    () => new Vector3(
-                        pelvisTrans.position.x,
-                        (pelvisTrans.position.y + spineTrans.position.y) / 2f,
-                        pelvisTrans.position.z
-                    ),
-                    () => new Vector3(
-                        pelvisTrans.eulerAngles.x + 90f,
-                        pelvisTrans.eulerAngles.y + 90f,
-                        pelvisTrans.eulerAngles.z
-                    )
-                );
+            DragPelvis dragPelvis = DragPoint[Bone.Pelvis].AddComponent<DragPelvis>();
+            dragPelvis.Initialize(maid, BoneTransform[Bone.Pelvis],
+                () => new Vector3(
+                    pelvisTrans.position.x,
+                    (pelvisTrans.position.y + spineTrans.position.y) / 2f,
+                    pelvisTrans.position.z
+                ),
+                () => new Vector3(
+                    pelvisTrans.eulerAngles.x + 90f,
+                    pelvisTrans.eulerAngles.y + 90f,
+                    pelvisTrans.eulerAngles.z
+                )
+            );
+            dragPelvis.DragEvent += OnDragEvent;
 
+            // Left Mune Dragpoint
             DragPoint[Bone.MuneL] = MakeDragPoint(PrimitiveType.Sphere, new Vector3(0.12f, 0.12f, 0.12f), transparentBlue);
             DragMune dragMuneL = DragPoint[Bone.MuneL].AddComponent<DragMune>();
             Transform[] muneIKChainL = new Transform[3] {
@@ -311,7 +353,9 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 () => (BoneTransform[Bone.MuneL].position + BoneTransform[Bone.MuneSubL].position) / 2f,
                 () => Vector3.zero
             );
+            dragMuneL.DragEvent += OnDragEvent;
 
+            // Right Mune Dragpoint
             DragPoint[Bone.MuneR] = MakeDragPoint(PrimitiveType.Sphere, new Vector3(0.12f, 0.12f, 0.12f), transparentBlue);
             DragMune dragMuneR = DragPoint[Bone.MuneR].AddComponent<DragMune>();
             Transform[] muneIKChainR = new Transform[3] {
@@ -323,7 +367,9 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 () => (BoneTransform[Bone.MuneR].position + BoneTransform[Bone.MuneSubR].position) / 2f,
                 () => Vector3.zero
             );
+            dragMuneR.DragEvent += OnDragEvent;
 
+            // Left Arm Dragpoint
             GameObject[] ikChainArmL = MakeIKChainDragPoint(
                 new Transform[3] {
                     BoneTransform[Bone.ClavicleL],
@@ -346,6 +392,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             DragPoint[Bone.ForearmL] = ikChainArmL[1];
             DragPoint[Bone.HandL] = ikChainArmL[2];
 
+            // Right Arm Dragpoint
             GameObject[] ikChainArmR = MakeIKChainDragPoint(
                 new Transform[3] {
                     BoneTransform[Bone.ClavicleR],
@@ -368,6 +415,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             DragPoint[Bone.ForearmR] = ikChainArmR[1];
             DragPoint[Bone.HandR] = ikChainArmR[2];
 
+            // Left Leg Dragpoint
             GameObject[] ikChainLegL = MakeIKChainDragPoint(
                 new Transform[3] {
                     BoneTransform[Bone.ThighL],
@@ -389,6 +437,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             DragPoint[Bone.CalfL] = ikChainLegL[1];
             DragPoint[Bone.FootL] = ikChainLegL[2];
 
+            // Right Arm Dragpoint
             GameObject[] ikChainLegR = MakeIKChainDragPoint(
                 new Transform[3] {
                     BoneTransform[Bone.ThighR],
@@ -414,17 +463,20 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             GameObject.Destroy(ikChainLegL[0]);
             GameObject.Destroy(ikChainLegR[0]);
 
+            // Spine Dragpoints
             for (Bone bone = Bone.Neck; bone <= Bone.ThighR; ++bone)
             {
                 Transform pos = BoneTransform[bone];
                 DragPoint[bone] = MakeDragPoint(PrimitiveType.Sphere, limbDragPointSize, transparentBlue);
-                DragPoint[bone].AddComponent<DragSpine>()
-                    .Initialize(BoneTransform[bone], maid,
-                        () => pos.position,
-                        () => Vector3.zero
-                    );
+                DragSpine dragSpine = DragPoint[bone].AddComponent<DragSpine>();
+                dragSpine.Initialize(BoneTransform[bone], maid,
+                    () => pos.position,
+                    () => Vector3.zero
+                );
+                dragSpine.DragEvent += OnDragEvent;
             }
 
+            // Finger Dragpoints
             for (Bone finger = Bone.Finger0L; finger <= Bone.Finger4R; finger += 4)
             {
                 for (int i = 0; i < 3; i++)
@@ -438,13 +490,13 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                     };
                     Func<Vector3> pos = () => BoneTransform[bone].position;
                     bool baseFinger = i == 0;
-                    // if (i == 0)
-                    //     DragPoint[bone].AddComponent<DragJointForearm>().Initialize(trans, true, maid, pos, () => Vector3.zero);
-                    // else
-                    DragPoint[bone].AddComponent<DragJointFinger>().Initialize(trans, baseFinger, maid, pos, () => Vector3.zero);
+                    DragJointFinger dragJointFinger = DragPoint[bone].AddComponent<DragJointFinger>();
+                    dragJointFinger.Initialize(trans, baseFinger, maid, pos, () => Vector3.zero);
+                    dragJointFinger.DragEvent += OnDragEvent;
                 }
             }
 
+            // Toe Dragpoints
             for (Bone toe = Bone.Toe0L; toe <= Bone.Toe2R; toe += 3)
             {
                 for (int i = 0; i < 2; i++)
@@ -458,7 +510,9 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                     };
                     Func<Vector3> pos = () => BoneTransform[bone].position;
                     bool baseFinger = i == 0;
-                    DragPoint[bone].AddComponent<DragJointFinger>().Initialize(trans, baseFinger, maid, pos, () => Vector3.zero);
+                    DragJointFinger dragJointFinger = DragPoint[bone].AddComponent<DragJointFinger>();
+                    dragJointFinger.Initialize(trans, baseFinger, maid, pos, () => Vector3.zero);
+                    dragJointFinger.DragEvent += OnDragEvent;
                 }
             }
 
@@ -568,5 +622,10 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         {
             SelectMaid?.Invoke(this, args);
         }
+
+        private void OnDragEvent(object sender, EventArgs args)
+        {
+            this.meido.IsStop = true;
+        }
     }
 }

+ 21 - 15
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Managers/MeidoManager.cs

@@ -11,21 +11,18 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         private int undress = 0;
         public Meido[] meidos { get; private set; }
         public List<Meido> ActiveMeidoList { get; private set; }
-        public Meido ActiveMeido { get; private set; }
+        public Meido ActiveMeido => ActiveMeidoList.Count > 0 ? ActiveMeidoList[selectedMeido] : null;
         public bool HasActiveMeido => ActiveMeido != null;
         public bool IsFade { get; set; } = false;
         public int numberOfMeidos;
         public event EventHandler<MeidoChangeEventArgs> SelectMeido;
         public event EventHandler CalledMeidos;
+        public event EventHandler AnimeChange;
         private int selectedMeido = 0;
         public int SelectedMeido
         {
             get => selectedMeido;
-            set
-            {
-                selectedMeido = Mathf.Clamp(value, 0, ActiveMeidoList.Count);
-                ActiveMeido = ActiveMeidoList.Count > 0 ? ActiveMeidoList[selectedMeido] : null;
-            }
+            private set => selectedMeido = Mathf.Clamp(value, 0, ActiveMeidoList.Count);
         }
         public bool IsBusy
         {
@@ -52,13 +49,9 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             MaidSwitcherPane.MaidChange += ChangeMeido;
             MaidSwitcherPane.meidoManager = this;
 
-            ActiveMeido = null;
-
             for (int stockMaidIndex = 0; stockMaidIndex < numberOfMeidos; stockMaidIndex++)
             {
                 meidos[stockMaidIndex] = new Meido(stockMaidIndex);
-                meidos[stockMaidIndex].SelectMeido += ChangeMeido;
-                meidos[stockMaidIndex].BodyLoad += EndCallMeidos;
             }
         }
 
@@ -101,6 +94,9 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             foreach (Meido meido in ActiveMeidoList)
             {
                 meido.Unload();
+                meido.SelectMeido -= ChangeMeido;
+                meido.BodyLoad -= EndCallMeidos;
+                meido.AnimeChange -= OnAnimeChangeEvent;
             }
             ActiveMeidoList.Clear();
         }
@@ -110,6 +106,9 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             foreach (Meido meido in meidos)
             {
                 meido.Deactivate();
+                meido.SelectMeido -= ChangeMeido;
+                meido.BodyLoad -= EndCallMeidos;
+                meido.AnimeChange -= OnAnimeChangeEvent;
             }
             ActiveMeidoList.Clear();
         }
@@ -124,6 +123,9 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             {
                 Meido meido = meidos[slot];
                 ActiveMeidoList.Add(meido);
+                meido.SelectMeido += ChangeMeido;
+                meido.BodyLoad += EndCallMeidos;
+                meido.AnimeChange += OnAnimeChangeEvent;
             }
 
             for (int i = 0; i < ActiveMeidoList.Count; i++)
@@ -138,17 +140,17 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             if (selectedMaids.Count == 0) EndCallMeidos(this, EventArgs.Empty);
         }
 
-        private void OnSelectMeido(MeidoChangeEventArgs args)
+        private void OnAnimeChangeEvent(object sender, EventArgs args)
         {
-            SelectMeido?.Invoke(this, args);
+            this.AnimeChange?.Invoke(this.ActiveMeido, EventArgs.Empty);
         }
 
-        public void SetMeidoPose(string pose, int meidoIndex = -1)
+        private void OnSelectMeido(MeidoChangeEventArgs args)
         {
-            Meido meido = meidoIndex == -1 ? ActiveMeido : ActiveMeidoList[meidoIndex];
-            meido.SetPose(pose);
+            SelectMeido?.Invoke(this, args);
         }
 
+
         private void ChangeMeido(object sender, MeidoChangeEventArgs args)
         {
             SelectedMeido = args.selected;
@@ -162,6 +164,10 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 IsFade = false;
                 GameMain.Instance.MainCamera.FadeIn(1f);
                 CalledMeidos?.Invoke(this, EventArgs.Empty);
+                foreach (Meido meido in ActiveMeidoList)
+                {
+                    meido.BodyLoad -= EndCallMeidos;
+                }
             }
         }
     }

+ 6 - 1
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Meido/IK/BaseDrag.cs

@@ -50,7 +50,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             }
         }
         private static bool IsGizmoDrag => Utility.GetFieldValue<GizmoRender, bool>(null, "is_drag_");
-
+        public event EventHandler DragEvent;
         protected enum DragType
         {
             None, Select,
@@ -158,5 +158,10 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 transform.eulerAngles = rotation();
             }
         }
+
+        protected void OnDragEvent()
+        {
+            DragEvent?.Invoke(null, EventArgs.Empty);
+        }
     }
 }

+ 1 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Meido/IK/DragHead.cs

@@ -97,6 +97,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 if (isPlaying)
                 {
                     maid.GetAnimation().Stop();
+                    OnDragEvent();
                 }
             }
 

+ 1 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Meido/IK/DragJointFinger.cs

@@ -70,6 +70,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             if (isPlaying)
             {
                 maid.GetAnimation().Stop();
+                OnDragEvent();
             }
 
             IKCtrlData ikData = maid.body0.IKCtrl.GetIKData("左手");

+ 1 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Meido/IK/DragJointForearm.cs

@@ -68,6 +68,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             if (isPlaying)
             {
                 maid.GetAnimation().Stop();
+                OnDragEvent();
             }
 
             IKCtrlData ikData = maid.body0.IKCtrl.GetIKData("左手");

+ 1 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Meido/IK/DragJointHand.cs

@@ -87,6 +87,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             if (isPlaying)
             {
                 maid.GetAnimation().Stop();
+                OnDragEvent();
             }
 
             IKCtrlData ikData = maid.body0.IKCtrl.GetIKData("左手");

+ 1 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Meido/IK/DragMune.cs

@@ -80,6 +80,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             if (isPlaying)
             {
                 maid.GetAnimation().Stop();
+                OnDragEvent();
             }
 
             IKCtrlData ikData = maid.body0.IKCtrl.GetIKData("左手");

+ 1 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Meido/IK/DragPelvis.cs

@@ -40,6 +40,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             if (isPlaying)
             {
                 maid.GetAnimation().Stop();
+                OnDragEvent();
             }
 
             Vector3 pos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, worldPoint.z);

+ 1 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Meido/IK/DragSpine.cs

@@ -32,6 +32,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             if (isPlaying)
             {
                 maid.GetAnimation().Stop();
+                OnDragEvent();
             }
 
             if (dragType == DragType.None)

+ 1 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Meido/IK/DragTorso.cs

@@ -44,6 +44,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             if (isPlaying)
             {
                 maid.GetAnimation().Stop();
+                OnDragEvent();
             }
 
             Vector3 pos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, worldPoint.z);

+ 79 - 1
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Meido/Meido.cs

@@ -10,6 +10,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
     {
         private static CharacterMgr characterMgr = GameMain.Instance.CharacterMgr;
         public readonly int stockNo;
+        public readonly PoseInfo defaultPose = new PoseInfo(0, 0, "pose_taiki_f");
         public Maid Maid { get; private set; }
         public Texture2D Image { get; private set; }
         public string FirstName { get; private set; }
@@ -20,12 +21,32 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         private DragPointManager dragPointManager;
         public event EventHandler<MeidoChangeEventArgs> SelectMeido;
         public event EventHandler BodyLoad;
+        public event EventHandler AnimeChange;
         private bool isLoading = false;
+        private bool isIK = false;
+        public bool IsIK
+        {
+            get => this.isIK;
+            private set => this.isIK = value;
+        }
+        private bool isStop = false;
+        public bool IsStop
+        {
+            get => isStop;
+            set
+            {
+                isStop = value;
+                this.AnimeChange?.Invoke(this, EventArgs.Empty);
+                if (!isStop) this.SetPose(this.poseInfo.PoseName);
+            }
+        }
+        public bool IsBone { get; set; } = false;
         public bool Visible
         {
             get => Maid.Visible;
             set => Maid.Visible = value;
         }
+        public PoseInfo poseInfo;
 
         public Meido(int stockMaidIndex)
         {
@@ -34,6 +55,8 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             this.Image = Maid.GetThumIcon();
             this.FirstName = Maid.status.firstName;
             this.LastName = Maid.status.lastName;
+            this.poseInfo = defaultPose;
+            // I don't know why I put this here. Must've fixed something with proc loading
             Maid.boAllProcPropBUSY = false;
         }
 
@@ -65,7 +88,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             }
             else
             {
-                SetPose("pose_taiki_f");
+                SetPose(defaultPose);
             }
 
             if (dragPointManager == null)
@@ -76,6 +99,10 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             else
             {
                 dragPointManager.Activate();
+
+                this.IsIK = true;
+                this.IsStop = false;
+                this.IsBone = false;
             }
 
             Maid.body0.boHeadToCam = true;
@@ -103,12 +130,18 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             Maid.Visible = false;
 
             dragPointManager?.Deactivate();
+            this.IsIK = false;
+            this.IsStop = false;
+            this.IsBone = false;
         }
 
         public void Deactivate()
         {
             Unload();
             dragPointManager?.Destroy();
+            this.IsIK = false;
+            this.IsStop = false;
+            this.IsBone = false;
             Maid.SetPos(Vector3.zero);
             Maid.SetRot(Vector3.zero);
             Maid.SetPosOffset(Vector3.zero);
@@ -119,6 +152,12 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             Maid.DelPrefabAll();
         }
 
+        public void SetPose(PoseInfo poseInfo)
+        {
+            this.poseInfo = poseInfo;
+            SetPose(poseInfo.PoseName);
+        }
+
         public void SetPose(string pose)
         {
             if (pose.StartsWith(Constants.customPosePath))
@@ -218,9 +257,33 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             body.FixVisibleFlag(false);
         }
 
+        public void SetIKActive(bool active)
+        {
+            this.IsIK = active;
+            if (dragPointManager == null) this.IsIK = false;
+            else
+            {
+                if (this.IsIK) dragPointManager.Activate();
+                else dragPointManager.Deactivate();
+            }
+        }
+
+        public void IKRelease()
+        {
+            if (!Maid.GetAnimation().isPlaying)
+            {
+                this.IsStop = false;
+                this.SetPose(this.poseInfo.PoseName);
+            }
+        }
+
         private void OnBodyLoad()
         {
             BodyLoad?.Invoke(this, EventArgs.Empty);
+
+            this.IsIK = true;
+            this.IsStop = false;
+            this.IsBone = false;
         }
 
         private void OnMeidoSelect(MeidoChangeEventArgs args)
@@ -229,3 +292,18 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         }
     }
 }
+
+public struct PoseInfo
+{
+    public int PoseGroupIndex { get; private set; }
+    public int PoseIndex { get; private set; }
+    public string PoseName { get; private set; }
+    public bool IsCustomPose { get; private set; }
+    public PoseInfo(int poseGroup, int pose, string poseName, bool isCustomPose = false)
+    {
+        this.PoseGroupIndex = poseGroup;
+        this.PoseIndex = pose;
+        this.PoseName = poseName;
+        this.IsCustomPose = isCustomPose;
+    }
+}