MaidFaceSliderPane.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. using System;
  2. using System.IO;
  3. using System.Collections.Generic;
  4. using Newtonsoft.Json;
  5. using UnityEngine;
  6. using System.Linq;
  7. namespace COM3D2.MeidoPhotoStudio.Plugin
  8. {
  9. using static Meido;
  10. public class MaidFaceSliderPane : BasePane
  11. {
  12. // TODO: Consider placing in external file to be user editable
  13. private static readonly Dictionary<string, float> SliderLimits = new Dictionary<string, float>()
  14. {
  15. // Eye Shut
  16. ["eyeclose"] = 1f,
  17. // Eye Smile
  18. ["eyeclose2"] = 1f,
  19. // Glare
  20. ["eyeclose3"] = 1f,
  21. // Wide Eyes
  22. ["eyebig"] = 1f,
  23. // Wink 1
  24. ["eyeclose6"] = 1f,
  25. // Wink 2
  26. ["eyeclose5"] = 1f,
  27. // Highlight
  28. ["hitomih"] = 2f,
  29. // Pupil Size
  30. ["hitomis"] = 3f,
  31. // Brow 1
  32. ["mayuha"] = 1f,
  33. // Brow 2
  34. ["mayuw"] = 1f,
  35. // Brow Up
  36. ["mayuup"] = 1f,
  37. // Brow Down 1
  38. ["mayuv"] = 1f,
  39. // Brow Down 2
  40. ["mayuvhalf"] = 1f,
  41. // Mouth Open 1
  42. ["moutha"] = 1f,
  43. // Mouth Open 2
  44. ["mouths"] = 1f,
  45. // Mouth Narrow
  46. ["mouthc"] = 1f,
  47. // Mouth Widen
  48. ["mouthi"] = 1f,
  49. // Smile
  50. ["mouthup"] = 1.4f,
  51. // Frown
  52. ["mouthdw"] = 1f,
  53. // Mouth Pucker
  54. ["mouthhe"] = 1f,
  55. // Grin
  56. ["mouthuphalf"] = 2f,
  57. // Tongue Out
  58. ["tangout"] = 1f,
  59. // Tongue Up
  60. ["tangup"] = 1f,
  61. // Tongue Base
  62. ["tangopen"] = 1f
  63. };
  64. private readonly MeidoManager meidoManager;
  65. private readonly Dictionary<string, BaseControl> faceControls;
  66. private bool hasTangOpen;
  67. public MaidFaceSliderPane(MeidoManager meidoManager)
  68. {
  69. this.meidoManager = meidoManager;
  70. faceControls = new Dictionary<string, BaseControl>();
  71. foreach (string key in faceKeys)
  72. {
  73. string uiName = Translation.Get("faceBlendValues", key);
  74. Slider slider = new Slider(uiName, 0f, SliderLimits[key]);
  75. string myKey = key;
  76. slider.ControlEvent += (s, a) => SetFaceValue(myKey, slider.Value);
  77. faceControls[key] = slider;
  78. }
  79. foreach (string key in faceToggleKeys)
  80. {
  81. string uiName = Translation.Get("faceBlendValues", key);
  82. Toggle toggle = new Toggle(uiName);
  83. string myKey = key;
  84. toggle.ControlEvent += (s, a) => SetFaceValue(myKey, toggle.Value);
  85. faceControls[key] = toggle;
  86. }
  87. InitializeSliderLimits(faceControls);
  88. }
  89. private static void InitializeSliderLimits(Dictionary<string, BaseControl> controls)
  90. {
  91. try
  92. {
  93. string sliderLimitsPath = Path.Combine(Constants.databasePath, "face_slider_limits.json");
  94. string sliderLimitsJson = File.ReadAllText(sliderLimitsPath);
  95. foreach (var kvp in JsonConvert.DeserializeObject<Dictionary<string, float>>(sliderLimitsJson))
  96. {
  97. string key = kvp.Key;
  98. if (faceKeys.Contains(key) && controls.ContainsKey(key))
  99. {
  100. float limit = kvp.Value;
  101. limit = kvp.Value >= 1f ? limit : SliderLimits[key];
  102. Slider slider = (Slider)controls[kvp.Key];
  103. slider.SetBounds(slider.Left, limit);
  104. }
  105. else Utility.LogWarning($"'{key}' is not a valid face key");
  106. }
  107. }
  108. catch (IOException e)
  109. {
  110. Utility.LogWarning($"Could not open face slider limit database because {e.Message}");
  111. }
  112. catch (Exception e)
  113. {
  114. Utility.LogError($"Could not apply face slider limit database because {e.Message}");
  115. }
  116. }
  117. protected override void ReloadTranslation()
  118. {
  119. for (int i = 0; i < faceKeys.Length; i++)
  120. {
  121. Slider slider = (Slider)faceControls[faceKeys[i]];
  122. slider.Label = Translation.Get("faceBlendValues", faceKeys[i]);
  123. }
  124. for (int i = 0; i < faceToggleKeys.Length; i++)
  125. {
  126. Toggle toggle = (Toggle)faceControls[faceToggleKeys[i]];
  127. toggle.Label = Translation.Get("faceBlendValues", faceToggleKeys[i]);
  128. }
  129. }
  130. public override void UpdatePane()
  131. {
  132. updating = true;
  133. Meido meido = meidoManager.ActiveMeido;
  134. for (int i = 0; i < faceKeys.Length; i++)
  135. {
  136. Slider slider = (Slider)faceControls[faceKeys[i]];
  137. try
  138. {
  139. slider.Value = meido.GetFaceBlendValue(faceKeys[i]);
  140. }
  141. catch { }
  142. }
  143. for (int i = 0; i < faceToggleKeys.Length; i++)
  144. {
  145. string hash = faceToggleKeys[i];
  146. Toggle toggle = (Toggle)faceControls[hash];
  147. toggle.Value = meido.GetFaceBlendValue(hash) > 0f;
  148. if (hash == "toothoff") toggle.Value = !toggle.Value;
  149. }
  150. hasTangOpen = meido.Body.Face.morph.Contains("tangopen");
  151. updating = false;
  152. }
  153. public override void Draw()
  154. {
  155. GUI.enabled = meidoManager.HasActiveMeido;
  156. DrawSliders("eyeclose", "eyeclose2");
  157. DrawSliders("eyeclose3", "eyebig");
  158. DrawSliders("eyeclose6", "eyeclose5");
  159. DrawSliders("hitomih", "hitomis");
  160. DrawSliders("mayuha", "mayuw");
  161. DrawSliders("mayuup", "mayuv");
  162. DrawSliders("mayuvhalf");
  163. DrawSliders("moutha", "mouths");
  164. DrawSliders("mouthc", "mouthi");
  165. DrawSliders("mouthup", "mouthdw");
  166. DrawSliders("mouthhe", "mouthuphalf");
  167. DrawSliders("tangout", "tangup");
  168. if (hasTangOpen) DrawSliders("tangopen");
  169. MpsGui.WhiteLine();
  170. DrawToggles("hoho2", "shock", "nosefook");
  171. DrawToggles("namida", "yodare", "toothoff");
  172. DrawToggles("tear1", "tear2", "tear3");
  173. DrawToggles("hohos", "hoho", "hohol");
  174. GUI.enabled = true;
  175. }
  176. private void DrawSliders(params string[] keys)
  177. {
  178. GUILayout.BeginHorizontal();
  179. foreach (string key in keys) faceControls[key].Draw(MpsGui.HalfSlider);
  180. GUILayout.EndHorizontal();
  181. }
  182. private void DrawToggles(params string[] keys)
  183. {
  184. GUILayout.BeginHorizontal();
  185. foreach (string key in keys) faceControls[key].Draw();
  186. GUILayout.EndHorizontal();
  187. }
  188. private void SetFaceValue(string key, float value)
  189. {
  190. if (updating) return;
  191. meidoManager.ActiveMeido.SetFaceBlendValue(key, value);
  192. }
  193. private void SetFaceValue(string key, bool value)
  194. {
  195. float max = (key == "hoho" || key == "hoho2") ? 0.5f : 1f;
  196. if (key == "toothoff") value = !value;
  197. SetFaceValue(key, value ? max : 0f);
  198. }
  199. }
  200. }