habeebweeb пре 4 година
родитељ
комит
bf1a9fecc7

+ 7 - 1
COM3D2.MeidoPhotoStudio.Plugin/Config/MeidoPhotoStudio/Translations/en/translation.ui.json

@@ -112,6 +112,7 @@
         "detail": "Detailed Clothing"
     },
     "handPane": {
+        "header": "Hand Preset",
         "saveToggle": "Save Hand",
         "categoryHeader": "Category",
         "nameHeader": "Name",
@@ -121,8 +122,13 @@
         "leftHand": "Left"
     },
     "copyPosePane": {
+        "header": "Copy IK",
         "copyButton": "Copy"
     },
+    "flipIK": {
+        "header": "Flip IK",
+        "flipButton": "Flip"
+    },
     "voiceLines": {
         "speak": "Speak",
         "speakEro": "H Lines"
@@ -190,7 +196,7 @@
         "header": "My Room"
     },
     "modPropsPane": {
-        "header": "Mod Props",
+        "header": "Mod Props"
     },
     "movementCube": {
         "header": "Movement Cube",

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

@@ -21,8 +21,11 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         private Toggle freeLookToggle;
         private Toggle savePoseToggle;
         private Toggle saveHandToggle;
+        private Button flipButton;
         private bool savePoseMode = false;
         private bool saveHandMode = false;
+        private string handPresetHeader;
+        private string flipIKHeader;
 
         public PoseWindowPane(MeidoManager meidoManager, MaidSwitcherPane maidSwitcherPane)
         {
@@ -52,6 +55,12 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 
             this.handPresetPane = AddPane(new HandPresetPane(meidoManager));
             this.saveHandPane = AddPane(new SaveHandPane(meidoManager));
+
+            this.flipButton = new Button(Translation.Get("flipIK", "flipButton"));
+            this.flipButton.ControlEvent += (s, a) => this.meidoManager.ActiveMeido.Flip();
+
+            this.handPresetHeader = Translation.Get("handPane", "header");
+            this.flipIKHeader = Translation.Get("flipIK", "header");
         }
 
         protected override void ReloadTranslation()
@@ -59,6 +68,8 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             this.freeLookToggle.Label = Translation.Get("freeLook", "freeLookToggle");
             this.savePoseToggle.Label = Translation.Get("posePane", "saveToggle");
             this.saveHandToggle.Label = Translation.Get("handPane", "saveToggle");
+            this.flipButton.Label = Translation.Get("flipIK", "flipButton");
+            this.handPresetHeader = Translation.Get("handPane", "header");
         }
 
         public override void Draw()
@@ -85,6 +96,8 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             maidIKPane.Draw();
 
             GUI.enabled = this.meidoManager.HasActiveMeido;
+            MiscGUI.Header(this.handPresetHeader);
+            MiscGUI.WhiteLine();
             saveHandToggle.Draw();
             GUI.enabled = true;
 
@@ -93,6 +106,13 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 
             copyPosePane.Draw();
 
+            GUILayout.BeginHorizontal();
+            GUI.enabled = this.meidoManager.HasActiveMeido;
+            GUILayout.Label(this.flipIKHeader, GUILayout.ExpandWidth(false));
+            flipButton.Draw(GUILayout.ExpandWidth(false));
+            GUI.enabled = true;
+            GUILayout.EndHorizontal();
+
             GUILayout.EndScrollView();
         }
 

+ 7 - 1
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/GUI/Panes/PoseWindowPanes/CopyPosePane.cs

@@ -17,6 +17,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 ? this.meidoManager.ActiveMeidoList[this.copyMeidoSlot[this.meidoDropdown.SelectedItemIndex]]
                 : null;
         }
+        private string copyIKHeader;
 
         public CopyPosePane(MeidoManager meidoManager)
         {
@@ -26,6 +27,8 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
 
             this.copyButton = new Button(Translation.Get("copyPosePane", "copyButton"));
             this.copyButton.ControlEvent += (s, a) => CopyPose();
+
+            this.copyIKHeader = Translation.Get("copyPosePane", "header");
         }
 
         protected override void ReloadTranslation()
@@ -35,16 +38,19 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 this.meidoDropdown.SetDropdownItem(0, Translation.Get("systemMessage", "noMaids"));
             }
             this.copyButton.Label = Translation.Get("copyPosePane", "copyButton");
+            this.copyIKHeader = Translation.Get("copyPosePane", "header");
         }
 
         public override void Draw()
         {
             GUI.enabled = PlentyOfMaids;
+            MiscGUI.Header(copyIKHeader);
+            MiscGUI.WhiteLine();
             GUILayout.BeginHorizontal();
             this.meidoDropdown.Draw(GUILayout.Width(160f));
             this.copyButton.Draw(GUILayout.ExpandWidth(false));
             GUILayout.EndHorizontal();
-            GUI.enabled = false;
+            GUI.enabled = true;
         }
 
         public override void UpdatePane()

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

@@ -102,6 +102,13 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             }
         }
 
+        public void Flip()
+        {
+            if (this.dragPointManager == null) return;
+            IsStop = true;
+            this.dragPointManager.Flip();
+        }
+
         public byte[] SerializePose()
         {
             CacheBoneDataArray cache = this.Maid.gameObject.GetComponent<CacheBoneDataArray>();

+ 94 - 8
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Meido/MeidoDragPointManager.cs

@@ -1,6 +1,7 @@
 using System;
 using System.IO;
 using System.Collections.Generic;
+using System.Linq;
 using UnityEngine;
 
 namespace COM3D2.MeidoPhotoStudio.Plugin
@@ -147,18 +148,103 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             return BoneTransform[PointToBone[point]];
         }
 
+        public void Flip()
+        {
+            Bone[] single = new[] { Bone.Pelvis, Bone.Spine, Bone.Spine0a, Bone.Spine1, Bone.Spine1a, Bone.Neck };
+            Bone[] pair = new[] {
+                Bone.ClavicleL, Bone.ClavicleR, Bone.UpperArmL, Bone.UpperArmR, Bone.ForearmL, Bone.ForearmR,
+                Bone.ForearmL, Bone.ForearmR, Bone.ThighL, Bone.ThighR, Bone.CalfL, Bone.CalfR,
+                Bone.HandL, Bone.HandR, Bone.FootL, Bone.FootR
+            };
+
+            List<Vector3> singleRotations = single.Select(bone => BoneTransform[bone].eulerAngles).ToList();
+            List<Vector3> pairRotations = pair.Select(bone => BoneTransform[bone].eulerAngles).ToList();
+
+            Transform hip = BoneTransform[Bone.Hip];
+            Vector3 vecHip = hip.eulerAngles;
+
+            Transform hipL = maid.body0.GetBone("Hip_L");
+            Vector3 vecHipL = hipL.eulerAngles;
+
+            Transform hipR = maid.body0.GetBone("Hip_R");
+            Vector3 vecHipR = hipR.eulerAngles;
+
+            hip.rotation = Quaternion.Euler(
+                360f - (vecHip.x + 270f) - 270f, 360f - (vecHip.y + 90f) - 90f, 360f - vecHip.z
+            );
+
+            hipL.rotation = FlipRotation(vecHipR);
+            hipR.rotation = FlipRotation(vecHipL);
+
+            for (int i = 0; i < single.Length; i++)
+            {
+                Bone bone = single[i];
+                BoneTransform[bone].rotation = FlipRotation(singleRotations[i]);
+            }
+
+            for (int i = 0; i < pair.Length; i += 2)
+            {
+                Bone boneA = pair[i];
+                Bone boneB = pair[i + 1];
+                BoneTransform[boneA].rotation = FlipRotation(pairRotations[i + 1]);
+                BoneTransform[boneB].rotation = FlipRotation(pairRotations[i]);
+            }
+
+            byte[] leftHand = SerializeHand(right: false);
+            byte[] rightHand = SerializeHand(right: true);
+            DeserializeHand(leftHand, right: true, true);
+            DeserializeHand(rightHand, right: false, true);
+            leftHand = SerializeFoot(right: false);
+            rightHand = SerializeFoot(right: true);
+            DeserializeFoot(leftHand, right: true, true);
+            DeserializeFoot(rightHand, right: false, true);
+        }
+
+        private Quaternion FlipRotation(Vector3 rotation)
+        {
+            return Quaternion.Euler(360f - rotation.x, 360f - (rotation.y + 90f) - 90f, rotation.z);
+        }
+
         public byte[] SerializeHand(bool right)
         {
             Bone start = right ? Bone.Finger0R : Bone.Finger0L;
             Bone end = right ? Bone.Finger4R : Bone.Finger4L;
+            return SerializeFinger(start, end, right);
+        }
+
+        public void DeserializeHand(byte[] handBinary, bool right, bool mirroring = false)
+        {
+            Bone start = right ? Bone.Finger0R : Bone.Finger0L;
+            Bone end = right ? Bone.Finger4R : Bone.Finger4L;
+            DeserializeFinger(start, end, handBinary, right, mirroring);
+        }
+
+        public byte[] SerializeFoot(bool right)
+        {
+            Bone start = right ? Bone.Toe0R : Bone.Toe0L;
+            Bone end = right ? Bone.Toe2R : Bone.Toe2L;
+            return SerializeFinger(start, end, right);
+        }
+
+        public void DeserializeFoot(byte[] footBinary, bool right, bool mirroring = false)
+        {
+            Bone start = right ? Bone.Toe0R : Bone.Toe0L;
+            Bone end = right ? Bone.Toe2R : Bone.Toe2L;
+            DeserializeFinger(start, end, footBinary, right, mirroring);
+        }
+
+        private byte[] SerializeFinger(Bone start, Bone end, bool right)
+        {
+            int joints = BoneTransform[start].name.Split(' ')[2].StartsWith("Finger") ? 4 : 3;
 
             byte[] buf;
+
             using (MemoryStream memoryStream = new MemoryStream())
             using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
             {
-                for (Bone bone = start; bone <= end; bone += 4)
+                for (Bone bone = start; bone <= end; bone += joints)
                 {
-                    for (int i = 0; i < 3; i++)
+                    for (int i = 0; i < joints - 1; i++)
                     {
                         Quaternion localRotation = BoneTransform[bone + i].localRotation;
                         binaryWriter.Write(localRotation.x);
@@ -169,22 +255,22 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 }
                 buf = memoryStream.ToArray();
             }
+
             return buf;
         }
 
-        public void DeserializeHand(byte[] handBinary, bool right, bool mirroring = false)
+        private void DeserializeFinger(Bone start, Bone end, byte[] fingerBinary, bool right, bool mirroring = false)
         {
-            Bone start = right ? Bone.Finger0R : Bone.Finger0L;
-            Bone end = right ? Bone.Finger4R : Bone.Finger4L;
+            int joints = BoneTransform[start].name.Split(' ')[2].StartsWith("Finger") ? 4 : 3;
 
             int mirror = mirroring ? -1 : 1;
 
-            using (MemoryStream memoryStream = new MemoryStream(handBinary))
+            using (MemoryStream memoryStream = new MemoryStream(fingerBinary))
             using (BinaryReader binaryReader = new BinaryReader(memoryStream))
             {
-                for (Bone bone = start; bone <= end; bone += 4)
+                for (Bone bone = start; bone <= end; bone += joints)
                 {
-                    for (int i = 0; i < 3; i++)
+                    for (int i = 0; i < joints - 1; i++)
                     {
                         Vector4 vec4;
                         vec4.x = binaryReader.ReadSingle() * mirror;