ArrayExtensionMethods.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /**
  2. * Copyright(c) Live2D Inc. All rights reserved.
  3. *
  4. * Use of this source code is governed by the Live2D Open Software license
  5. * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
  6. */
  7. using Live2D.Cubism.Core.Unmanaged;
  8. using Live2D.Cubism.Framework;
  9. using System;
  10. using UnityEngine;
  11. namespace Live2D.Cubism.Core
  12. {
  13. /// <summary>
  14. /// Extension for Cubism related arrays.
  15. /// </summary>
  16. public static class ArrayExtensionMethods
  17. {
  18. #region Parameters
  19. /// <summary>
  20. /// Finds a <see cref="CubismParameter"/> by its ID.
  21. /// </summary>
  22. /// <param name="self">Container.</param>
  23. /// <param name="id">ID to match.</param>
  24. /// <returns>Parameter on success; <see langword="null"/> otherwise.</returns>
  25. public static CubismParameter FindById(this CubismParameter[] self, string id)
  26. {
  27. if (self == null)
  28. {
  29. return null;
  30. }
  31. for (var i = 0; i < self.Length; ++i)
  32. {
  33. if (self[i].name != id)
  34. {
  35. continue;
  36. }
  37. return self[i];
  38. }
  39. return null;
  40. }
  41. /// <summary>
  42. /// Revives (and sorts) <see cref="CubismParameter"/>s.
  43. /// </summary>
  44. /// <param name="self">Container.</param>
  45. /// <param name="model">TaskableModel to unmanaged model.</param>
  46. internal static void Revive(this CubismParameter[] self, CubismUnmanagedModel model)
  47. {
  48. Array.Sort(self, (a, b) => a.UnmanagedIndex - b.UnmanagedIndex);
  49. for (var i = 0; i < self.Length; ++i)
  50. {
  51. self[i].Revive(model);
  52. }
  53. }
  54. /// <summary>
  55. /// Writes opacities to unmanaged model.
  56. /// </summary>
  57. /// <param name="self">Source buffer.</param>
  58. /// <param name="unmanagedModel"></param>
  59. internal static void WriteTo(this CubismParameter[] self, CubismUnmanagedModel unmanagedModel)
  60. {
  61. // Get address.
  62. var unmanagedParameters = unmanagedModel.Parameters;
  63. var values = unmanagedParameters.Values;
  64. // Push.
  65. for (var i = 0; i < self.Length; ++i)
  66. {
  67. values[self[i].UnmanagedIndex] = self[i].Value;
  68. }
  69. }
  70. /// <summary>
  71. /// Writes opacities to unmanaged model.
  72. /// </summary>
  73. /// <param name="self">Source buffer.</param>
  74. /// <param name="unmanagedModel"></param>
  75. internal static void ReadFrom(this CubismParameter[] self, CubismUnmanagedModel unmanagedModel)
  76. {
  77. // Get address.
  78. var unmanagedParameters = unmanagedModel.Parameters;
  79. var values = unmanagedParameters.Values;
  80. // Pull.
  81. for (var i = 0; i < self.Length; ++i)
  82. {
  83. self[i].OverrideValue(values[self[i].UnmanagedIndex]);
  84. }
  85. }
  86. #endregion
  87. #region Parts
  88. /// <summary>
  89. /// Finds a <see cref="CubismPart"/> by its ID.
  90. /// </summary>
  91. /// <param name="self"><see langword="this"/>.</param>
  92. /// <param name="id">ID to match.</param>
  93. /// <returns>Part if found; <see langword="null"/> otherwise.</returns>
  94. public static CubismPart FindById(this CubismPart[] self, string id)
  95. {
  96. if (self == null)
  97. {
  98. return null;
  99. }
  100. for (var i = 0; i < self.Length; ++i)
  101. {
  102. if (self[i].name != id)
  103. {
  104. continue;
  105. }
  106. return self[i];
  107. }
  108. return null;
  109. }
  110. /// <summary>
  111. /// Revives (and sorts) <see cref="CubismPart"/>s.
  112. /// </summary>
  113. /// <param name="self">Container.</param>
  114. /// <param name="model">TaskableModel to unmanaged model.</param>
  115. internal static void Revive(this CubismPart[] self, CubismUnmanagedModel model)
  116. {
  117. Array.Sort(self, (a, b) => a.UnmanagedIndex - b.UnmanagedIndex);
  118. for (var i = 0; i < self.Length; ++i)
  119. {
  120. self[i].Revive(model);
  121. }
  122. }
  123. /// <summary>
  124. /// Writes opacities to unmanaged model.
  125. /// </summary>
  126. /// <param name="self">Source buffer.</param>
  127. /// <param name="unmanagedModel"></param>
  128. internal static void WriteTo(this CubismPart[] self, CubismUnmanagedModel unmanagedModel)
  129. {
  130. // Get address.
  131. var unmanagedParts = unmanagedModel.Parts;
  132. var opacities = unmanagedParts.Opacities;
  133. // Push.
  134. for (var i = 0; i < self.Length; ++i)
  135. {
  136. opacities[self[i].UnmanagedIndex] = self[i].Opacity;
  137. }
  138. }
  139. #endregion
  140. #region Drawables
  141. /// <summary>
  142. /// Finds a <see cref="CubismParameter"/> by its ID.
  143. /// </summary>
  144. /// <param name="self"><see langword="this"/>.</param>
  145. /// <param name="id">ID to match.</param>
  146. /// <returns>Part if found; <see langword="null"/> otherwise.</returns>
  147. public static CubismDrawable FindById(this CubismDrawable[] self, string id)
  148. {
  149. if (self == null)
  150. {
  151. return null;
  152. }
  153. for (var i = 0; i < self.Length; ++i)
  154. {
  155. if (self[i].name != id)
  156. {
  157. continue;
  158. }
  159. return self[i];
  160. }
  161. return null;
  162. }
  163. /// <summary>
  164. /// Revives (and sorts) <see cref="CubismDrawable"/>s.
  165. /// </summary>
  166. /// <param name="self">Container.</param>
  167. /// <param name="model">TaskableModel to unmanaged model.</param>
  168. internal static void Revive(this CubismDrawable[] self, CubismUnmanagedModel model)
  169. {
  170. Array.Sort(self, (a, b) => a.UnmanagedIndex - b.UnmanagedIndex);
  171. for (var i = 0; i < self.Length; ++i)
  172. {
  173. self[i].Revive(model);
  174. }
  175. }
  176. /// <summary>
  177. /// Reads new data from a model.
  178. /// </summary>
  179. /// <param name="self">Buffer to write to.</param>
  180. /// <param name="unmanagedModel">Unmanaged model to read from.</param>
  181. internal static unsafe void ReadFrom(this CubismDynamicDrawableData[] self, CubismUnmanagedModel unmanagedModel)
  182. {
  183. // Get addresses.
  184. var drawables = unmanagedModel.Drawables;
  185. var flags = drawables.DynamicFlags;
  186. var opacities = drawables.Opacities;
  187. var drawOrders = drawables.DrawOrders;
  188. var renderOrders = drawables.RenderOrders;
  189. var vertexPositions = drawables.VertexPositions;
  190. var multiplyColors = drawables.MultiplyColors;
  191. var screenColors = drawables.ScreenColors;
  192. // Pull data.
  193. for (var i = 0; i < self.Length; ++i)
  194. {
  195. var data = self[i];
  196. data.Flags = flags[i];
  197. data.Opacity = opacities[i];
  198. data.DrawOrder = drawOrders[i];
  199. data.RenderOrder = renderOrders[i];
  200. // Read vertex positions only if necessary.
  201. if (!data.AreVertexPositionsDirty)
  202. {
  203. continue;
  204. }
  205. // Copy vertex positions.
  206. fixed (Vector3* dataVertexPositions = data.VertexPositions)
  207. {
  208. for (var v = 0; v < data.VertexPositions.Length; ++v)
  209. {
  210. dataVertexPositions[v].x = vertexPositions[i][(v * 2) + 0];
  211. dataVertexPositions[v].y = vertexPositions[i][(v * 2) + 1];
  212. }
  213. }
  214. if (!data.IsBlendColorDirty)
  215. {
  216. continue;
  217. }
  218. var rgbaIndex = i * 4;
  219. data.MultiplyColor = new Color(multiplyColors[rgbaIndex], multiplyColors[rgbaIndex + 1], multiplyColors[rgbaIndex + 2], multiplyColors[rgbaIndex + 3]);
  220. data.ScreenColor = new Color(screenColors[rgbaIndex], screenColors[rgbaIndex + 1], screenColors[rgbaIndex + 2], screenColors[rgbaIndex + 3]);
  221. }
  222. // Clear dynamic flags.
  223. drawables.ResetDynamicFlags();
  224. }
  225. #endregion
  226. }
  227. }