/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html. */ using Live2D.Cubism.Core.Unmanaged; using System; using UnityEngine; namespace Live2D.Cubism.Core { /// /// Extension for Cubism related arrays. /// public static class ArrayExtensionMethods { #region Parameters /// /// Finds a by its ID. /// /// Container. /// ID to match. /// Parameter on success; otherwise. public static CubismParameter FindById(this CubismParameter[] self, string id) { if (self == null) { return null; } for (var i = 0; i < self.Length; ++i) { if (self[i].name != id) { continue; } return self[i]; } return null; } /// /// Revives (and sorts) s. /// /// Container. /// TaskableModel to unmanaged model. internal static void Revive(this CubismParameter[] self, CubismUnmanagedModel model) { Array.Sort(self, (a, b) => a.UnmanagedIndex - b.UnmanagedIndex); for (var i = 0; i < self.Length; ++i) { self[i].Revive(model); } } /// /// Writes opacities to unmanaged model. /// /// Source buffer. /// internal static void WriteTo(this CubismParameter[] self, CubismUnmanagedModel unmanagedModel) { // Get address. var unmanagedParameters = unmanagedModel.Parameters; var values = unmanagedParameters.Values; // Push. for (var i = 0; i < self.Length; ++i) { values[self[i].UnmanagedIndex] = self[i].Value; } } /// /// Writes opacities to unmanaged model. /// /// Source buffer. /// internal static void ReadFrom(this CubismParameter[] self, CubismUnmanagedModel unmanagedModel) { // Get address. var unmanagedParameters = unmanagedModel.Parameters; var values = unmanagedParameters.Values; // Pull. for (var i = 0; i < self.Length; ++i) { self[i].Value = values[self[i].UnmanagedIndex]; } } #endregion #region Parts /// /// Finds a by its ID. /// /// . /// ID to match. /// Part if found; otherwise. public static CubismPart FindById(this CubismPart[] self, string id) { if (self == null) { return null; } for (var i = 0; i < self.Length; ++i) { if (self[i].name != id) { continue; } return self[i]; } return null; } /// /// Revives (and sorts) s. /// /// Container. /// TaskableModel to unmanaged model. internal static void Revive(this CubismPart[] self, CubismUnmanagedModel model) { Array.Sort(self, (a, b) => a.UnmanagedIndex - b.UnmanagedIndex); for (var i = 0; i < self.Length; ++i) { self[i].Revive(model); } } /// /// Writes opacities to unmanaged model. /// /// Source buffer. /// internal static void WriteTo(this CubismPart[] self, CubismUnmanagedModel unmanagedModel) { // Get address. var unmanagedParts = unmanagedModel.Parts; var opacities = unmanagedParts.Opacities; // Push. for (var i = 0; i < self.Length; ++i) { opacities[self[i].UnmanagedIndex] = self[i].Opacity; } } #endregion #region Drawables /// /// Finds a by its ID. /// /// . /// ID to match. /// Part if found; otherwise. public static CubismDrawable FindById(this CubismDrawable[] self, string id) { if (self == null) { return null; } for (var i = 0; i < self.Length; ++i) { if (self[i].name != id) { continue; } return self[i]; } return null; } /// /// Revives (and sorts) s. /// /// Container. /// TaskableModel to unmanaged model. internal static void Revive(this CubismDrawable[] self, CubismUnmanagedModel model) { Array.Sort(self, (a, b) => a.UnmanagedIndex - b.UnmanagedIndex); for (var i = 0; i < self.Length; ++i) { self[i].Revive(model); } } /// /// Reads new data from a model. /// /// Buffer to write to. /// Unmanaged model to read from. internal static unsafe void ReadFrom(this CubismDynamicDrawableData[] self, CubismUnmanagedModel unmanagedModel) { // Get addresses. var drawables = unmanagedModel.Drawables; var flags = drawables.DynamicFlags; var opacities = drawables.Opacities; var drawOrders = drawables.DrawOrders; var renderOrders = drawables.RenderOrders; var vertexPositions = drawables.VertexPositions; // Pull data. for (var i = 0; i < self.Length; ++i) { var data = self[i]; data.Flags = flags[i]; data.Opacity = opacities[i]; data.DrawOrder = drawOrders[i]; data.RenderOrder = renderOrders[i]; // Read vertex positions only if necessary. if (!data.AreVertexPositionsDirty) { continue; } // Copy vertex positions. fixed (Vector3* dataVertexPositions = data.VertexPositions) { for (var v = 0; v < data.VertexPositions.Length; ++v) { dataVertexPositions[v].x = vertexPositions[i][(v * 2) + 0]; dataVertexPositions[v].y = vertexPositions[i][(v * 2) + 1]; } } } // Clear dynamic flags. drawables.ResetDynamicFlags(); } #endregion } }