Utility.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Text.RegularExpressions;
  7. using UnityEngine;
  8. namespace MeidoPhotoStudio.Plugin;
  9. public static class Utility
  10. {
  11. public static readonly BepInEx.Logging.ManualLogSource Logger =
  12. ManualLogSource;
  13. internal static readonly byte[] PngHeader = { 137, 80, 78, 71, 13, 10, 26, 10 };
  14. internal static readonly byte[] PngEnd = System.Text.Encoding.ASCII.GetBytes("IEND");
  15. internal static readonly Regex GuidRegEx =
  16. new(@"^[a-f0-9]{8}(\-[a-f0-9]{4}){3}\-[a-f0-9]{12}$", RegexOptions.IgnoreCase);
  17. internal static readonly GameObject MousePositionGameObject;
  18. internal static readonly MousePosition MousePositionValue;
  19. private const BindingFlags ReflectionFlags =
  20. BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
  21. private static readonly BepInEx.Logging.ManualLogSource ManualLogSource =
  22. BepInEx.Logging.Logger.CreateLogSource(MeidoPhotoStudio.PluginName);
  23. static Utility()
  24. {
  25. MousePositionGameObject = new();
  26. MousePositionValue = MousePositionGameObject.AddComponent<MousePosition>();
  27. }
  28. public enum ModKey
  29. {
  30. Control,
  31. Shift,
  32. Alt,
  33. }
  34. public static string Timestamp =>
  35. $"{DateTime.Now:yyyyMMddHHmmss}";
  36. public static Vector3 MousePosition =>
  37. MousePositionValue.Position;
  38. public static void LogInfo(object data) =>
  39. Logger.LogInfo(data);
  40. public static void LogMessage(object data) =>
  41. Logger.LogMessage(data);
  42. public static void LogWarning(object data) =>
  43. Logger.LogWarning(data);
  44. public static void LogError(object data) =>
  45. Logger.LogError(data);
  46. public static void LogDebug(object data) =>
  47. Logger.LogDebug(data);
  48. public static int Wrap(int value, int min, int max)
  49. {
  50. max--;
  51. return value < min ? max : value > max ? min : value;
  52. }
  53. public static int GetPix(int num) =>
  54. (int)((1f + (Screen.width / 1280f - 1f) * 0.6f) * num);
  55. public static float Bound(float value, float left, float right) =>
  56. left > (double)right ? Mathf.Clamp(value, right, left) : Mathf.Clamp(value, left, right);
  57. public static int Bound(int value, int left, int right) =>
  58. left > right ? Mathf.Clamp(value, right, left) : Mathf.Clamp(value, left, right);
  59. public static Texture2D MakeTex(int width, int height, Color color)
  60. {
  61. var colors = new Color32[width * height];
  62. for (var i = 0; i < colors.Length; i++)
  63. colors[i] = color;
  64. var texture2D = new Texture2D(width, height);
  65. texture2D.SetPixels32(colors);
  66. texture2D.Apply();
  67. return texture2D;
  68. }
  69. public static FieldInfo GetFieldInfo<T>(string field) =>
  70. typeof(T).GetField(field, ReflectionFlags);
  71. public static TValue GetFieldValue<TType, TValue>(TType instance, string field)
  72. {
  73. var fieldInfo = GetFieldInfo<TType>(field);
  74. return fieldInfo is null || !fieldInfo.IsStatic && instance == null
  75. ? default
  76. : (TValue)fieldInfo.GetValue(instance);
  77. }
  78. public static void SetFieldValue<TType, TValue>(TType instance, string name, TValue value) =>
  79. GetFieldInfo<TType>(name).SetValue(instance, value);
  80. public static PropertyInfo GetPropertyInfo<T>(string field) =>
  81. typeof(T).GetProperty(field, ReflectionFlags);
  82. public static TValue GetPropertyValue<TType, TValue>(TType instance, string property)
  83. {
  84. var propertyInfo = GetPropertyInfo<TType>(property);
  85. return propertyInfo is null
  86. ? default
  87. : (TValue)propertyInfo.GetValue(instance, null);
  88. }
  89. public static void SetPropertyValue<TType, TValue>(TType instance, string name, TValue value) =>
  90. GetPropertyInfo<TType>(name).SetValue(instance, value, null);
  91. public static bool AnyMouseDown() =>
  92. Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1) || Input.GetMouseButtonDown(2);
  93. public static string ScreenshotFilename()
  94. {
  95. var screenShotDir = Path.Combine(GameMain.Instance.SerializeStorageManager.StoreDirectoryPath, "ScreenShot");
  96. if (!Directory.Exists(screenShotDir))
  97. Directory.CreateDirectory(screenShotDir);
  98. return Path.Combine(screenShotDir, $"img{Timestamp}.png");
  99. }
  100. public static string TempScreenshotFilename() =>
  101. Path.Combine(Path.GetTempPath(), $"cm3d2_{Guid.NewGuid()}.png");
  102. public static void ShowMouseExposition(string text, float time = 2f)
  103. {
  104. var mouseExposition = MouseExposition.GetObject();
  105. mouseExposition.SetText(text, time);
  106. }
  107. public static bool IsGuidString(string guid) =>
  108. !string.IsNullOrEmpty(guid) && guid.Length is 36 && GuidRegEx.IsMatch(guid);
  109. public static string HandItemToOdogu(string menu)
  110. {
  111. menu = menu.Substring(menu.IndexOf('_') + 1);
  112. menu = menu.Substring(0, menu.IndexOf("_i_.menu", StringComparison.OrdinalIgnoreCase));
  113. menu = $"odogu_{menu}";
  114. return menu;
  115. }
  116. public static void FixGameObjectScale(GameObject go)
  117. {
  118. var scale = go.transform.localScale;
  119. var largest = Mathf.Max(scale.x, Mathf.Max(scale.y, scale.z));
  120. go.transform.localScale = Vector3.one * (float)Math.Round(largest, 3);
  121. }
  122. public static string SanitizePathPortion(string path)
  123. {
  124. var invalid = Path.GetInvalidFileNameChars();
  125. path = path.Trim();
  126. path = string.Join("_", path.Split(invalid)).Replace(".", string.Empty).Trim('_');
  127. return path;
  128. }
  129. public static string GP01FbFaceHash(TMorph face, string hash)
  130. {
  131. if (face.bodyskin.PartsVersion < 120 || hash is "eyeclose3" || !hash.StartsWith("eyeclose"))
  132. return hash;
  133. if (hash is "eyeclose")
  134. hash += '1';
  135. hash += TMorph.crcFaceTypesStr[(int)face.GetFaceTypeGP01FB()];
  136. return hash;
  137. }
  138. public static void ResizeToFit(Texture2D texture, int maxWidth, int maxHeight)
  139. {
  140. var width = texture.width;
  141. var height = texture.height;
  142. if (width == maxWidth && height == maxHeight)
  143. return;
  144. var scale = Mathf.Min(maxWidth / (float)width, maxHeight / (float)height);
  145. width = Mathf.RoundToInt(width * scale);
  146. height = Mathf.RoundToInt(height * scale);
  147. TextureScale.Bilinear(texture, width, height);
  148. }
  149. public static bool BytesEqual(byte[] buffer, byte[] other)
  150. {
  151. if (buffer.Length != other.Length)
  152. return false;
  153. for (var i = 0; i < buffer.Length; i++)
  154. if (buffer[i] != other[i])
  155. return false;
  156. return true;
  157. }
  158. public static bool IsPngFile(Stream stream)
  159. {
  160. var buffer = new byte[8];
  161. stream.Read(buffer, 0, 8);
  162. return BytesEqual(buffer, PngHeader);
  163. }
  164. public static bool SeekPngEnd(Stream stream)
  165. {
  166. var buffer = new byte[8];
  167. stream.Read(buffer, 0, 8);
  168. if (!BytesEqual(buffer, PngHeader))
  169. return false;
  170. buffer = new byte[4];
  171. do
  172. {
  173. stream.Read(buffer, 0, 4);
  174. if (BitConverter.IsLittleEndian)
  175. Array.Reverse(buffer);
  176. var length = BitConverter.ToUInt32(buffer, 0);
  177. stream.Read(buffer, 0, 4);
  178. stream.Seek(length + 4L, SeekOrigin.Current);
  179. }
  180. while (!BytesEqual(buffer, PngEnd));
  181. return true;
  182. }
  183. public static void WriteToFile(string name, IEnumerable<string> list)
  184. {
  185. if (Path.GetExtension(name) is not ".txt")
  186. name += ".txt";
  187. File.WriteAllLines(Path.Combine(Constants.ConfigPath, name), list.ToArray());
  188. }
  189. public static void WriteToFile(string name, byte[] data) =>
  190. File.WriteAllBytes(Path.Combine(Constants.ConfigPath, name), data);
  191. }