MeidoDragPointManager.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using UnityEngine;
  6. namespace MeidoPhotoStudio.Plugin;
  7. public class MeidoDragPointManager
  8. {
  9. private static readonly Dictionary<AttachPoint, Bone> PointToBone = new()
  10. {
  11. [AttachPoint.Head] = Bone.Head,
  12. [AttachPoint.Neck] = Bone.HeadNub,
  13. [AttachPoint.UpperArmL] = Bone.UpperArmL,
  14. [AttachPoint.UpperArmR] = Bone.UpperArmR,
  15. [AttachPoint.ForearmL] = Bone.ForearmL,
  16. [AttachPoint.ForearmR] = Bone.ForearmR,
  17. [AttachPoint.MuneL] = Bone.MuneL,
  18. [AttachPoint.MuneR] = Bone.MuneR,
  19. [AttachPoint.HandL] = Bone.HandL,
  20. [AttachPoint.HandR] = Bone.HandR,
  21. [AttachPoint.Pelvis] = Bone.Pelvis,
  22. [AttachPoint.ThighL] = Bone.ThighL,
  23. [AttachPoint.ThighR] = Bone.ThighR,
  24. [AttachPoint.CalfL] = Bone.CalfL,
  25. [AttachPoint.CalfR] = Bone.CalfR,
  26. [AttachPoint.FootL] = Bone.FootL,
  27. [AttachPoint.FootR] = Bone.FootR,
  28. [AttachPoint.Spine1a] = Bone.Spine1a,
  29. [AttachPoint.Spine1] = Bone.Spine1,
  30. [AttachPoint.Spine0a] = Bone.Spine0a,
  31. [AttachPoint.Spine0] = Bone.Spine,
  32. };
  33. private static readonly Bone[] SpineBones =
  34. {
  35. Bone.Neck, Bone.Spine, Bone.Spine0a, Bone.Spine1, Bone.Spine1a, Bone.Hip, Bone.ThighL, Bone.ThighR,
  36. };
  37. private static bool cubeActive;
  38. private static bool cubeSmall;
  39. private static EventHandler cubeActiveChange;
  40. private static EventHandler cubeSmallChange;
  41. private readonly Meido meido;
  42. private readonly Dictionary<Bone, DragPointMeido> dragPoints = new();
  43. private Dictionary<Bone, Transform> boneTransform = new();
  44. private DragPointBody dragBody;
  45. private DragPointBody dragCube;
  46. private bool initialized;
  47. private bool isBone;
  48. private bool active = true;
  49. public MeidoDragPointManager(Meido meido) =>
  50. this.meido = meido;
  51. public event EventHandler<MeidoUpdateEventArgs> SelectMaid;
  52. private enum Bone
  53. {
  54. // Head
  55. Head,
  56. HeadNub,
  57. ClavicleL,
  58. ClavicleR,
  59. // Arms
  60. UpperArmL,
  61. UpperArmR,
  62. ForearmL,
  63. ForearmR,
  64. // IKHandL and IKHandR
  65. HandL,
  66. HandR,
  67. // Mune
  68. MuneL,
  69. MuneSubL,
  70. MuneR,
  71. MuneSubR,
  72. // Spine
  73. Neck,
  74. Spine,
  75. Spine0a,
  76. Spine1,
  77. Spine1a,
  78. ThighL,
  79. ThighR,
  80. // Hip
  81. Pelvis,
  82. Hip,
  83. // Legs
  84. CalfL,
  85. CalfR,
  86. FootL,
  87. FootR,
  88. // Dragpoint specific
  89. Cube,
  90. Body,
  91. Torso,
  92. // Fingers
  93. Finger0L,
  94. Finger01L,
  95. Finger02L,
  96. Finger0NubL,
  97. Finger1L,
  98. Finger11L,
  99. Finger12L,
  100. Finger1NubL,
  101. Finger2L,
  102. Finger21L,
  103. Finger22L,
  104. Finger2NubL,
  105. Finger3L,
  106. Finger31L,
  107. Finger32L,
  108. Finger3NubL,
  109. Finger4L,
  110. Finger41L,
  111. Finger42L,
  112. Finger4NubL,
  113. Finger0R,
  114. Finger01R,
  115. Finger02R,
  116. Finger0NubR,
  117. Finger1R,
  118. Finger11R,
  119. Finger12R,
  120. Finger1NubR,
  121. Finger2R,
  122. Finger21R,
  123. Finger22R,
  124. Finger2NubR,
  125. Finger3R,
  126. Finger31R,
  127. Finger32R,
  128. Finger3NubR,
  129. Finger4R,
  130. Finger41R,
  131. Finger42R,
  132. Finger4NubR,
  133. // Toes
  134. Toe0L,
  135. Toe01L,
  136. Toe0NubL,
  137. Toe1L,
  138. Toe11L,
  139. Toe1NubL,
  140. Toe2L,
  141. Toe21L,
  142. Toe2NubL,
  143. Toe0R,
  144. Toe01R,
  145. Toe0NubR,
  146. Toe1R,
  147. Toe11R,
  148. Toe1NubR,
  149. Toe2R,
  150. Toe21R,
  151. Toe2NubR,
  152. }
  153. public static bool CubeActive
  154. {
  155. get => cubeActive;
  156. set
  157. {
  158. if (value == cubeActive)
  159. return;
  160. cubeActive = value;
  161. cubeActiveChange?.Invoke(null, EventArgs.Empty);
  162. }
  163. }
  164. public static bool CubeSmall
  165. {
  166. get => cubeSmall;
  167. set
  168. {
  169. if (value == cubeSmall)
  170. return;
  171. cubeSmall = value;
  172. cubeSmallChange?.Invoke(null, EventArgs.Empty);
  173. }
  174. }
  175. public bool IsBone
  176. {
  177. get => isBone;
  178. set
  179. {
  180. if (!initialized)
  181. return;
  182. if (isBone == value)
  183. return;
  184. isBone = value;
  185. foreach (var dragPoint in dragPoints.Values)
  186. dragPoint.IsBone = isBone;
  187. foreach (var bone in SpineBones)
  188. dragPoints[bone].gameObject.SetActive(isBone);
  189. }
  190. }
  191. public bool Active
  192. {
  193. get => active;
  194. set
  195. {
  196. if (!initialized)
  197. return;
  198. if (active == value)
  199. return;
  200. active = value;
  201. foreach (var dragPoint in dragPoints.Values)
  202. dragPoint.gameObject.SetActive(active);
  203. foreach (var bone in SpineBones)
  204. dragPoints[bone].gameObject.SetActive(active && IsBone);
  205. var head = (DragPointHead)dragPoints[Bone.Head];
  206. head.gameObject.SetActive(true);
  207. head.IsIK = !active;
  208. dragBody.IsIK = !active;
  209. }
  210. }
  211. public void Deserialize(BinaryReader reader)
  212. {
  213. var sixtyFourFlag = reader.ReadBoolean();
  214. var upperBone = sixtyFourFlag ? Bone.Finger4NubR : Bone.Toe2NubR;
  215. // finger rotations. Toe rotations as well if sixtyFourFlag is false
  216. for (var bone = Bone.Finger0L; bone <= upperBone; ++bone)
  217. boneTransform[bone].localRotation = reader.ReadQuaternion();
  218. var bones = sixtyFourFlag
  219. ? new[]
  220. {
  221. Bone.Pelvis, Bone.Spine, Bone.Spine0a, Bone.Spine1, Bone.Spine1a, Bone.Neck, Bone.UpperArmL,
  222. Bone.UpperArmR, Bone.ForearmL, Bone.ForearmR, Bone.ThighL, Bone.ThighR, Bone.CalfL, Bone.CalfR,
  223. Bone.HandL, Bone.HandR, Bone.FootL, Bone.FootR,
  224. }
  225. : new[]
  226. {
  227. Bone.Hip, Bone.Pelvis, Bone.Spine, Bone.Spine0a, Bone.Spine1, Bone.Spine1a, Bone.Neck,
  228. Bone.ClavicleL, Bone.ClavicleR, Bone.UpperArmL, Bone.UpperArmR, Bone.ForearmL, Bone.ForearmR,
  229. Bone.ThighL, Bone.ThighR, Bone.CalfL, Bone.CalfR, Bone.MuneL, Bone.MuneR, Bone.MuneSubL,
  230. Bone.MuneSubR, Bone.HandL, Bone.HandR, Bone.FootL, Bone.FootR,
  231. };
  232. var localRotationIndex = Array.IndexOf(bones, Bone.CalfR);
  233. for (var i = 0; i < bones.Length; i++)
  234. {
  235. var bone = bones[i];
  236. if (bone is Bone.ClavicleL)
  237. {
  238. /*
  239. * Versions of MM possibly serialized ClavicleL improperly.
  240. * At least I think that's what happened otherwise why would they make this check at all.
  241. * https://git.coder.horse/meidomustard/modifiedMM/src/master/MultipleMaids/CM3D2/MultipleMaids/Plugin/MultipleMaids.Update.cs#L4355
  242. *
  243. * Just look at the way MM serializes rotations.
  244. * https://git.coder.horse/meidomustard/modifiedMM/src/master/MultipleMaids/CM3D2/MultipleMaids/Plugin/MultipleMaids.Update.cs#L2364
  245. * It is most definitely possible MM dev missed a component.
  246. *
  247. * Also why is strArray9.Length == 2 acceptable? If the length were only 2,
  248. * float.Parse(strArray9[2]) would throw an index out of range exception???
  249. */
  250. if (!reader.ReadBoolean())
  251. {
  252. reader.ReadQuaternion();
  253. continue;
  254. }
  255. }
  256. var rotation = reader.ReadQuaternion();
  257. if (sixtyFourFlag || i > localRotationIndex)
  258. boneTransform[bone].localRotation = rotation;
  259. else
  260. boneTransform[bone].rotation = rotation;
  261. }
  262. // WHY????
  263. GameMain.Instance.StartCoroutine(ApplyHipPosition(reader.ReadVector3()));
  264. }
  265. public void Flip()
  266. {
  267. meido.Stop = true;
  268. var single = new[] { Bone.Pelvis, Bone.Spine, Bone.Spine0a, Bone.Spine1, Bone.Spine1a, Bone.Neck };
  269. var pair = new[]
  270. {
  271. Bone.ClavicleL, Bone.ClavicleR, Bone.UpperArmL, Bone.UpperArmR, Bone.ForearmL, Bone.ForearmR,
  272. Bone.ThighL, Bone.ThighR, Bone.CalfL, Bone.CalfR, Bone.HandL, Bone.HandR, Bone.FootL, Bone.FootR,
  273. };
  274. var singleRotations = single.Select(bone => boneTransform[bone].eulerAngles).ToList();
  275. var pairRotations = pair.Select(bone => boneTransform[bone].eulerAngles).ToList();
  276. var hip = boneTransform[Bone.Hip];
  277. var vecHip = hip.eulerAngles;
  278. var hipL = meido.Maid.body0.GetBone("Hip_L");
  279. var vecHipL = hipL.eulerAngles;
  280. var hipR = meido.Maid.body0.GetBone("Hip_R");
  281. var vecHipR = hipR.eulerAngles;
  282. hip.rotation =
  283. Quaternion.Euler(360f - (vecHip.x + 270f) - 270f, 360f - (vecHip.y + 90f) - 90f, 360f - vecHip.z);
  284. hipL.rotation = FlipRotation(vecHipR);
  285. hipR.rotation = FlipRotation(vecHipL);
  286. for (var i = 0; i < single.Length; i++)
  287. {
  288. var bone = single[i];
  289. boneTransform[bone].rotation = FlipRotation(singleRotations[i]);
  290. }
  291. for (var i = 0; i < pair.Length; i += 2)
  292. {
  293. var boneA = pair[i];
  294. var boneB = pair[i + 1];
  295. boneTransform[boneA].rotation = FlipRotation(pairRotations[i + 1]);
  296. boneTransform[boneB].rotation = FlipRotation(pairRotations[i]);
  297. }
  298. var leftHand = SerializeHand(right: false);
  299. var rightHand = SerializeHand(right: true);
  300. DeserializeHand(leftHand, right: true, true);
  301. DeserializeHand(rightHand, right: false, true);
  302. leftHand = SerializeFoot(right: false);
  303. rightHand = SerializeFoot(right: true);
  304. DeserializeFoot(leftHand, right: true, true);
  305. DeserializeFoot(rightHand, right: false, true);
  306. }
  307. public Transform GetAttachPointTransform(AttachPoint point) =>
  308. point is AttachPoint.None ? null : boneTransform[PointToBone[point]];
  309. public byte[] SerializeHand(bool right)
  310. {
  311. var start = right ? Bone.Finger0R : Bone.Finger0L;
  312. var end = right ? Bone.Finger4R : Bone.Finger4L;
  313. return SerializeFinger(start, end);
  314. }
  315. public void DeserializeHand(byte[] handBinary, bool right, bool mirroring = false)
  316. {
  317. var start = right ? Bone.Finger0R : Bone.Finger0L;
  318. var end = right ? Bone.Finger4R : Bone.Finger4L;
  319. DeserializeFinger(start, end, handBinary, mirroring);
  320. }
  321. public byte[] SerializeFoot(bool right)
  322. {
  323. var start = right ? Bone.Toe0R : Bone.Toe0L;
  324. var end = right ? Bone.Toe2R : Bone.Toe2L;
  325. return SerializeFinger(start, end);
  326. }
  327. public void DeserializeFoot(byte[] footBinary, bool right, bool mirroring = false)
  328. {
  329. var start = right ? Bone.Toe0R : Bone.Toe0L;
  330. var end = right ? Bone.Toe2R : Bone.Toe2L;
  331. DeserializeFinger(start, end, footBinary, mirroring);
  332. }
  333. public void Destroy()
  334. {
  335. foreach (var dragPoint in dragPoints.Values)
  336. if (dragPoint)
  337. UnityEngine.Object.Destroy(dragPoint.gameObject);
  338. if (dragCube)
  339. UnityEngine.Object.Destroy(dragCube.gameObject);
  340. if (dragBody)
  341. UnityEngine.Object.Destroy(dragBody.gameObject);
  342. boneTransform.Clear();
  343. dragPoints.Clear();
  344. cubeActiveChange -= OnCubeActive;
  345. cubeSmallChange -= OnCubeSmall;
  346. initialized = false;
  347. }
  348. public void Initialize()
  349. {
  350. if (initialized)
  351. return;
  352. initialized = true;
  353. cubeActiveChange += OnCubeActive;
  354. cubeSmallChange += OnCubeSmall;
  355. InitializeBones();
  356. InitializeDragPoints();
  357. SetDragPointScale(meido.Maid.transform.localScale.x);
  358. }
  359. public void SetDragPointScale(float scale)
  360. {
  361. foreach (var dragPoint in dragPoints.Values)
  362. dragPoint.DragPointScale = scale;
  363. dragBody.DragPointScale = scale;
  364. }
  365. private static DragPointLimb[] MakeArmChain(Transform lower, Meido meido)
  366. {
  367. var limbDragPointSize = Vector3.one * 0.12f;
  368. var realLower = CMT.SearchObjName(meido.Body.goSlot[0].obj_tr, lower.name, false);
  369. var dragPoints = new DragPointLimb[3];
  370. for (var i = dragPoints.Length - 1; i >= 0; i--)
  371. {
  372. var joint = lower;
  373. var positionJoint = realLower;
  374. dragPoints[i] = DragPoint.Make<DragPointLimb>(PrimitiveType.Sphere, limbDragPointSize);
  375. dragPoints[i].Initialize(meido, () => positionJoint.position, () => Vector3.zero);
  376. dragPoints[i].Set(joint);
  377. dragPoints[i].AddGizmo();
  378. dragPoints[i].Gizmo.SetAlternateTarget(positionJoint);
  379. lower = lower.parent;
  380. realLower = realLower.parent;
  381. }
  382. return dragPoints;
  383. }
  384. private static DragPointFinger[] MakeFingerChain(Transform lower, Meido meido)
  385. {
  386. var fingerDragPointSize = Vector3.one * 0.01f;
  387. var dragPoints = new DragPointFinger[3];
  388. var realLower = CMT.SearchObjName(meido.Body.goSlot[0].obj_tr, lower.parent.name, false);
  389. for (var i = dragPoints.Length - 1; i >= 0; i--)
  390. {
  391. var joint = lower;
  392. var positionJoint = realLower;
  393. dragPoints[i] = DragPoint.Make<DragPointFinger>(PrimitiveType.Sphere, fingerDragPointSize);
  394. dragPoints[i].Initialize(meido, () => positionJoint.position, () => Vector3.zero);
  395. dragPoints[i].Set(joint);
  396. lower = lower.parent;
  397. realLower = realLower.parent;
  398. }
  399. return dragPoints;
  400. }
  401. /*
  402. Somebody smarter than me please help me find a way to do this better T_T
  403. inb4 for loop.
  404. */
  405. private System.Collections.IEnumerator ApplyHipPosition(Vector3 hipPosition)
  406. {
  407. boneTransform[Bone.Hip].position = hipPosition;
  408. yield return new WaitForEndOfFrame();
  409. boneTransform[Bone.Hip].position = hipPosition;
  410. yield return new WaitForEndOfFrame();
  411. boneTransform[Bone.Hip].position = hipPosition;
  412. }
  413. private Quaternion FlipRotation(Vector3 rotation) =>
  414. Quaternion.Euler(360f - rotation.x, 360f - (rotation.y + 90f) - 90f, rotation.z);
  415. private byte[] SerializeFinger(Bone start, Bone end)
  416. {
  417. var joints = boneTransform[start].name.Split(' ')[2].StartsWith("Finger") ? 4 : 3;
  418. byte[] buf;
  419. using var memoryStream = new MemoryStream();
  420. using var binaryWriter = new BinaryWriter(memoryStream);
  421. for (var bone = start; bone <= end; bone += joints)
  422. for (var i = 0; i < joints - 1; i++)
  423. binaryWriter.WriteQuaternion(boneTransform[bone + i].localRotation);
  424. buf = memoryStream.ToArray();
  425. return buf;
  426. }
  427. private void DeserializeFinger(Bone start, Bone end, byte[] fingerBinary, bool mirroring = false)
  428. {
  429. var joints = boneTransform[start].name.Split(' ')[2].StartsWith("Finger") ? 4 : 3;
  430. var mirror = mirroring ? -1 : 1;
  431. using var memoryStream = new MemoryStream(fingerBinary);
  432. using var binaryReader = new BinaryReader(memoryStream);
  433. for (var bone = start; bone <= end; bone += joints)
  434. for (var i = 0; i < joints - 1; i++)
  435. boneTransform[bone + i].localRotation = new(
  436. binaryReader.ReadSingle() * mirror,
  437. binaryReader.ReadSingle() * mirror,
  438. binaryReader.ReadSingle(),
  439. binaryReader.ReadSingle());
  440. }
  441. private void InitializeDragPoints()
  442. {
  443. dragCube = DragPoint.Make<DragPointBody>(PrimitiveType.Cube, Vector3.one * 0.12f);
  444. dragCube.Initialize(() => meido.Maid.transform.position, () => Vector3.zero);
  445. dragCube.Set(meido.Maid.transform);
  446. dragCube.IsCube = true;
  447. dragCube.ConstantScale = true;
  448. dragCube.Select += OnSelectBody;
  449. dragCube.EndScale += OnSetDragPointScale;
  450. dragCube.gameObject.SetActive(CubeActive);
  451. dragBody = DragPoint.Make<DragPointBody>(PrimitiveType.Capsule, new Vector3(0.2f, 0.3f, 0.24f));
  452. dragBody.Initialize(
  453. () => new(
  454. (boneTransform[Bone.Hip].position.x + boneTransform[Bone.Spine0a].position.x) / 2f,
  455. (boneTransform[Bone.Spine1].position.y + boneTransform[Bone.Spine0a].position.y) / 2f,
  456. (boneTransform[Bone.Spine0a].position.z + boneTransform[Bone.Hip].position.z) / 2f),
  457. () => new(
  458. boneTransform[Bone.Spine0a].eulerAngles.x,
  459. boneTransform[Bone.Spine0a].eulerAngles.y,
  460. boneTransform[Bone.Spine0a].eulerAngles.z + 90f));
  461. dragBody.Set(meido.Maid.transform);
  462. dragBody.Select += OnSelectBody;
  463. dragBody.EndScale += OnSetDragPointScale;
  464. // Neck Dragpoint
  465. var dragNeck = DragPoint.Make<DragPointHead>(PrimitiveType.Sphere, new(0.2f, 0.24f, 0.2f));
  466. dragNeck.Initialize(
  467. meido,
  468. () => new(
  469. boneTransform[Bone.Head].position.x,
  470. (boneTransform[Bone.Head].position.y * 1.2f + boneTransform[Bone.HeadNub].position.y * 0.8f) / 2f,
  471. boneTransform[Bone.Head].position.z),
  472. () => new(
  473. boneTransform[Bone.Head].eulerAngles.x,
  474. boneTransform[Bone.Head].eulerAngles.y,
  475. boneTransform[Bone.Head].eulerAngles.z + 90f));
  476. dragNeck.Set(boneTransform[Bone.Neck]);
  477. dragNeck.Select += OnSelectFace;
  478. dragPoints[Bone.Head] = dragNeck;
  479. // Head Dragpoint
  480. var dragHead = DragPoint.Make<DragPointSpine>(PrimitiveType.Sphere, Vector3.one * 0.045f);
  481. dragHead.Initialize(meido, () => boneTransform[Bone.Head].position, () => Vector3.zero);
  482. dragHead.Set(boneTransform[Bone.Head]);
  483. dragHead.AddGizmo();
  484. dragPoints[Bone.HeadNub] = dragHead;
  485. // Torso Dragpoint
  486. var spineTrans1 = boneTransform[Bone.Spine1];
  487. var spineTrans2 = boneTransform[Bone.Spine1a];
  488. var dragTorso = DragPoint.Make<DragPointTorso>(PrimitiveType.Capsule, new Vector3(0.2f, 0.19f, 0.24f));
  489. dragTorso.Initialize(
  490. meido,
  491. () => new(spineTrans1.position.x, spineTrans2.position.y, spineTrans1.position.z - 0.05f),
  492. () => new(spineTrans1.eulerAngles.x, spineTrans1.eulerAngles.y, spineTrans1.eulerAngles.z + 90f));
  493. dragTorso.Set(boneTransform[Bone.Spine1a]);
  494. dragPoints[Bone.Torso] = dragTorso;
  495. // Pelvis Dragpoint
  496. var pelvisTrans = boneTransform[Bone.Pelvis];
  497. var spineTrans = boneTransform[Bone.Spine];
  498. var dragPelvis = DragPoint.Make<DragPointPelvis>(PrimitiveType.Capsule, new(0.2f, 0.15f, 0.24f));
  499. dragPelvis.Initialize(
  500. meido,
  501. () => new(
  502. pelvisTrans.position.x, (pelvisTrans.position.y + spineTrans.position.y) / 2f, pelvisTrans.position.z),
  503. () => new(pelvisTrans.eulerAngles.x + 90f, pelvisTrans.eulerAngles.y + 90f, pelvisTrans.eulerAngles.z));
  504. dragPelvis.Set(boneTransform[Bone.Pelvis]);
  505. dragPoints[Bone.Pelvis] = dragPelvis;
  506. InitializeMuneDragPoint(left: true);
  507. InitializeMuneDragPoint(left: false);
  508. var armDragPointL = MakeArmChain(boneTransform[Bone.HandL], meido);
  509. dragPoints[Bone.UpperArmL] = armDragPointL[0];
  510. dragPoints[Bone.ForearmL] = armDragPointL[1];
  511. dragPoints[Bone.HandL] = armDragPointL[2];
  512. var armDragPointR = MakeArmChain(boneTransform[Bone.HandR], meido);
  513. dragPoints[Bone.UpperArmR] = armDragPointR[0];
  514. dragPoints[Bone.ForearmR] = armDragPointR[1];
  515. dragPoints[Bone.HandR] = armDragPointR[2];
  516. var legDragPointL = MakeLegChain(boneTransform[Bone.FootL]);
  517. dragPoints[Bone.CalfL] = legDragPointL[0];
  518. dragPoints[Bone.FootL] = legDragPointL[1];
  519. var legDragPointR = MakeLegChain(boneTransform[Bone.FootR]);
  520. dragPoints[Bone.CalfR] = legDragPointR[0];
  521. dragPoints[Bone.FootR] = legDragPointR[1];
  522. InitializeSpineDragPoint(SpineBones);
  523. for (var bone = Bone.Finger4NubR; bone >= Bone.Finger0L; bone -= 4)
  524. {
  525. var chain = MakeFingerChain(boneTransform[bone], meido);
  526. var i = 2;
  527. for (var joint = bone - 1; joint > bone - 4; joint--)
  528. {
  529. dragPoints[joint] = chain[i];
  530. i--;
  531. }
  532. }
  533. MakeToeChain(Bone.Toe0L, Bone.Toe2R);
  534. }
  535. private void InitializeMuneDragPoint(bool left)
  536. {
  537. var mune = left ? Bone.MuneL : Bone.MuneR;
  538. var sub = left ? Bone.MuneSubL : Bone.MuneSubR;
  539. var muneDragPoint = DragPoint.Make<DragPointMune>(PrimitiveType.Sphere, Vector3.one * 0.12f);
  540. muneDragPoint.Initialize(
  541. meido,
  542. () => (boneTransform[mune].position + boneTransform[sub].position) / 2f,
  543. () => Vector3.zero);
  544. muneDragPoint.Set(boneTransform[sub]);
  545. dragPoints[mune] = muneDragPoint;
  546. }
  547. private DragPointLimb[] MakeLegChain(Transform lower)
  548. {
  549. var limbDragPointSize = Vector3.one * 0.12f;
  550. var dragPoints = new DragPointLimb[2];
  551. for (var i = dragPoints.Length - 1; i >= 0; i--)
  552. {
  553. var joint = lower;
  554. dragPoints[i] = DragPoint.Make<DragPointLimb>(PrimitiveType.Sphere, limbDragPointSize);
  555. dragPoints[i].Initialize(meido, () => joint.position, () => Vector3.zero);
  556. dragPoints[i].Set(joint);
  557. dragPoints[i].AddGizmo();
  558. lower = lower.parent;
  559. }
  560. return dragPoints;
  561. }
  562. private void MakeToeChain(Bone start, Bone end)
  563. {
  564. const int joints = 3;
  565. var fingerDragPointSize = Vector3.one * 0.01f;
  566. for (var bone = start; bone <= end; bone += joints)
  567. {
  568. for (var i = 1; i < joints; i++)
  569. {
  570. var trans = boneTransform[bone + i];
  571. var chain = DragPoint.Make<DragPointFinger>(PrimitiveType.Sphere, fingerDragPointSize);
  572. chain.Initialize(meido, () => trans.position, () => Vector3.zero);
  573. chain.Set(trans);
  574. dragPoints[bone + i] = chain;
  575. }
  576. }
  577. }
  578. private void InitializeSpineDragPoint(params Bone[] bones)
  579. {
  580. var spineDragPointSize = DragPointMeido.BoneScale;
  581. foreach (var bone in bones)
  582. {
  583. var spine = boneTransform[bone];
  584. var primitive = bone is Bone.Hip ? PrimitiveType.Cube : PrimitiveType.Sphere;
  585. var dragPoint = DragPoint.Make<DragPointSpine>(primitive, spineDragPointSize);
  586. dragPoint.Initialize(meido, () => spine.position, () => Vector3.zero);
  587. dragPoint.Set(spine);
  588. dragPoint.AddGizmo();
  589. dragPoints[bone] = dragPoint;
  590. dragPoints[bone].gameObject.SetActive(false);
  591. }
  592. }
  593. private void OnCubeActive(object sender, EventArgs args) =>
  594. dragCube.gameObject.SetActive(CubeActive);
  595. private void OnCubeSmall(object sender, EventArgs args) =>
  596. dragCube.DragPointScale = CubeSmall ? DragPointGeneral.SmallCube : 1f;
  597. private void OnSetDragPointScale(object sender, EventArgs args) =>
  598. SetDragPointScale(meido.Maid.transform.localScale.x);
  599. private void OnSelectBody(object sender, EventArgs args) =>
  600. SelectMaid?.Invoke(this, new MeidoUpdateEventArgs(meido.Slot, fromMaid: true, isBody: true));
  601. private void OnSelectFace(object sender, EventArgs args) =>
  602. SelectMaid?.Invoke(this, new MeidoUpdateEventArgs(meido.Slot, fromMaid: true, isBody: false));
  603. private void InitializeBones()
  604. {
  605. // TODO: Move to external file somehow
  606. var transform = meido.Body.m_Bones.transform;
  607. boneTransform = new()
  608. {
  609. [Bone.Head] = CMT.SearchObjName(transform, "Bip01 Head"),
  610. [Bone.Neck] = CMT.SearchObjName(transform, "Bip01 Neck"),
  611. [Bone.HeadNub] = CMT.SearchObjName(transform, "Bip01 HeadNub"),
  612. [Bone.MuneL] = CMT.SearchObjName(transform, "Mune_L"),
  613. [Bone.MuneSubL] = CMT.SearchObjName(transform, "Mune_L_sub"),
  614. [Bone.MuneR] = CMT.SearchObjName(transform, "Mune_R"),
  615. [Bone.MuneSubR] = CMT.SearchObjName(transform, "Mune_R_sub"),
  616. [Bone.Pelvis] = CMT.SearchObjName(transform, "Bip01 Pelvis"),
  617. [Bone.Hip] = CMT.SearchObjName(transform, "Bip01"),
  618. [Bone.Spine] = CMT.SearchObjName(transform, "Bip01 Spine"),
  619. [Bone.Spine0a] = CMT.SearchObjName(transform, "Bip01 Spine0a"),
  620. [Bone.Spine1] = CMT.SearchObjName(transform, "Bip01 Spine1"),
  621. [Bone.Spine1a] = CMT.SearchObjName(transform, "Bip01 Spine1a"),
  622. [Bone.ClavicleL] = CMT.SearchObjName(transform, "Bip01 L Clavicle"),
  623. [Bone.ClavicleR] = CMT.SearchObjName(transform, "Bip01 R Clavicle"),
  624. [Bone.UpperArmL] = CMT.SearchObjName(transform, "Bip01 L UpperArm"),
  625. [Bone.ForearmL] = CMT.SearchObjName(transform, "Bip01 L Forearm"),
  626. [Bone.HandL] = CMT.SearchObjName(transform, "Bip01 L Hand"),
  627. [Bone.UpperArmR] = CMT.SearchObjName(transform, "Bip01 R UpperArm"),
  628. [Bone.ForearmR] = CMT.SearchObjName(transform, "Bip01 R Forearm"),
  629. [Bone.HandR] = CMT.SearchObjName(transform, "Bip01 R Hand"),
  630. [Bone.ThighL] = CMT.SearchObjName(transform, "Bip01 L Thigh"),
  631. [Bone.CalfL] = CMT.SearchObjName(transform, "Bip01 L Calf"),
  632. [Bone.FootL] = CMT.SearchObjName(transform, "Bip01 L Foot"),
  633. [Bone.ThighR] = CMT.SearchObjName(transform, "Bip01 R Thigh"),
  634. [Bone.CalfR] = CMT.SearchObjName(transform, "Bip01 R Calf"),
  635. [Bone.FootR] = CMT.SearchObjName(transform, "Bip01 R Foot"),
  636. // fingers
  637. [Bone.Finger0L] = CMT.SearchObjName(transform, "Bip01 L Finger0"),
  638. [Bone.Finger01L] = CMT.SearchObjName(transform, "Bip01 L Finger01"),
  639. [Bone.Finger02L] = CMT.SearchObjName(transform, "Bip01 L Finger02"),
  640. [Bone.Finger0NubL] = CMT.SearchObjName(transform, "Bip01 L Finger0Nub"),
  641. [Bone.Finger1L] = CMT.SearchObjName(transform, "Bip01 L Finger1"),
  642. [Bone.Finger11L] = CMT.SearchObjName(transform, "Bip01 L Finger11"),
  643. [Bone.Finger12L] = CMT.SearchObjName(transform, "Bip01 L Finger12"),
  644. [Bone.Finger1NubL] = CMT.SearchObjName(transform, "Bip01 L Finger1Nub"),
  645. [Bone.Finger2L] = CMT.SearchObjName(transform, "Bip01 L Finger2"),
  646. [Bone.Finger21L] = CMT.SearchObjName(transform, "Bip01 L Finger21"),
  647. [Bone.Finger22L] = CMT.SearchObjName(transform, "Bip01 L Finger22"),
  648. [Bone.Finger2NubL] = CMT.SearchObjName(transform, "Bip01 L Finger2Nub"),
  649. [Bone.Finger3L] = CMT.SearchObjName(transform, "Bip01 L Finger3"),
  650. [Bone.Finger31L] = CMT.SearchObjName(transform, "Bip01 L Finger31"),
  651. [Bone.Finger32L] = CMT.SearchObjName(transform, "Bip01 L Finger32"),
  652. [Bone.Finger3NubL] = CMT.SearchObjName(transform, "Bip01 L Finger3Nub"),
  653. [Bone.Finger4L] = CMT.SearchObjName(transform, "Bip01 L Finger4"),
  654. [Bone.Finger41L] = CMT.SearchObjName(transform, "Bip01 L Finger41"),
  655. [Bone.Finger42L] = CMT.SearchObjName(transform, "Bip01 L Finger42"),
  656. [Bone.Finger4NubL] = CMT.SearchObjName(transform, "Bip01 L Finger4Nub"),
  657. [Bone.Finger0R] = CMT.SearchObjName(transform, "Bip01 R Finger0"),
  658. [Bone.Finger01R] = CMT.SearchObjName(transform, "Bip01 R Finger01"),
  659. [Bone.Finger02R] = CMT.SearchObjName(transform, "Bip01 R Finger02"),
  660. [Bone.Finger0NubR] = CMT.SearchObjName(transform, "Bip01 R Finger0Nub"),
  661. [Bone.Finger1R] = CMT.SearchObjName(transform, "Bip01 R Finger1"),
  662. [Bone.Finger11R] = CMT.SearchObjName(transform, "Bip01 R Finger11"),
  663. [Bone.Finger12R] = CMT.SearchObjName(transform, "Bip01 R Finger12"),
  664. [Bone.Finger1NubR] = CMT.SearchObjName(transform, "Bip01 R Finger1Nub"),
  665. [Bone.Finger2R] = CMT.SearchObjName(transform, "Bip01 R Finger2"),
  666. [Bone.Finger21R] = CMT.SearchObjName(transform, "Bip01 R Finger21"),
  667. [Bone.Finger22R] = CMT.SearchObjName(transform, "Bip01 R Finger22"),
  668. [Bone.Finger2NubR] = CMT.SearchObjName(transform, "Bip01 R Finger2Nub"),
  669. [Bone.Finger3R] = CMT.SearchObjName(transform, "Bip01 R Finger3"),
  670. [Bone.Finger31R] = CMT.SearchObjName(transform, "Bip01 R Finger31"),
  671. [Bone.Finger32R] = CMT.SearchObjName(transform, "Bip01 R Finger32"),
  672. [Bone.Finger3NubR] = CMT.SearchObjName(transform, "Bip01 R Finger3Nub"),
  673. [Bone.Finger4R] = CMT.SearchObjName(transform, "Bip01 R Finger4"),
  674. [Bone.Finger41R] = CMT.SearchObjName(transform, "Bip01 R Finger41"),
  675. [Bone.Finger42R] = CMT.SearchObjName(transform, "Bip01 R Finger42"),
  676. [Bone.Finger4NubR] = CMT.SearchObjName(transform, "Bip01 R Finger4Nub"),
  677. // Toes
  678. [Bone.Toe0L] = CMT.SearchObjName(transform, "Bip01 L Toe0"),
  679. [Bone.Toe01L] = CMT.SearchObjName(transform, "Bip01 L Toe01"),
  680. [Bone.Toe0NubL] = CMT.SearchObjName(transform, "Bip01 L Toe0Nub"),
  681. [Bone.Toe1L] = CMT.SearchObjName(transform, "Bip01 L Toe1"),
  682. [Bone.Toe11L] = CMT.SearchObjName(transform, "Bip01 L Toe11"),
  683. [Bone.Toe1NubL] = CMT.SearchObjName(transform, "Bip01 L Toe1Nub"),
  684. [Bone.Toe2L] = CMT.SearchObjName(transform, "Bip01 L Toe2"),
  685. [Bone.Toe21L] = CMT.SearchObjName(transform, "Bip01 L Toe21"),
  686. [Bone.Toe2NubL] = CMT.SearchObjName(transform, "Bip01 L Toe2Nub"),
  687. [Bone.Toe0R] = CMT.SearchObjName(transform, "Bip01 R Toe0"),
  688. [Bone.Toe01R] = CMT.SearchObjName(transform, "Bip01 R Toe01"),
  689. [Bone.Toe0NubR] = CMT.SearchObjName(transform, "Bip01 R Toe0Nub"),
  690. [Bone.Toe1R] = CMT.SearchObjName(transform, "Bip01 R Toe1"),
  691. [Bone.Toe11R] = CMT.SearchObjName(transform, "Bip01 R Toe11"),
  692. [Bone.Toe1NubR] = CMT.SearchObjName(transform, "Bip01 R Toe1Nub"),
  693. [Bone.Toe2R] = CMT.SearchObjName(transform, "Bip01 R Toe2"),
  694. [Bone.Toe21R] = CMT.SearchObjName(transform, "Bip01 R Toe21"),
  695. [Bone.Toe2NubR] = CMT.SearchObjName(transform, "Bip01 R Toe2Nub"),
  696. };
  697. }
  698. }