/** * 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 Live2D.Cubism.Framework; using UnityEngine; namespace Live2D.Cubism.Core { /// /// Single drawable. /// [CubismDontMoveOnReimport] public sealed class CubismDrawable : MonoBehaviour { #region Factory Methods /// /// Creates drawables for a . /// /// Handle to unmanaged model. /// Drawables root. internal static GameObject CreateDrawables(CubismUnmanagedModel unmanagedModel) { var root = new GameObject("Drawables"); // Create drawables. var unmanagedDrawables = unmanagedModel.Drawables; var buffer = new CubismDrawable[unmanagedDrawables.Count]; for (var i = 0; i < buffer.Length; ++i) { var proxy = new GameObject(); buffer[i] = proxy.AddComponent(); buffer[i].transform.SetParent(root.transform); buffer[i].Reset(unmanagedModel, i); } return root; } #endregion /// /// Unmanaged drawables from unmanaged model. /// private CubismUnmanagedDrawables UnmanagedDrawables { get; set; } /// /// backing field. /// [SerializeField, HideInInspector] private int _unmanagedIndex = -1; /// /// Position in unmanaged arrays. /// internal int UnmanagedIndex { get { return _unmanagedIndex; } private set { _unmanagedIndex = value; } } /// /// Copy of Id. /// public string Id { get { // Pull data. return UnmanagedDrawables.Ids[UnmanagedIndex]; } } /// /// Texture UnmanagedIndex. /// public int TextureIndex { get { // Pull data. return UnmanagedDrawables.TextureIndices[UnmanagedIndex]; } } /// /// Copy of the masks. /// public CubismDrawable[] Masks { get { var drawables = this .FindCubismModel(true) .Drawables; // Get addresses. var counts = UnmanagedDrawables.MaskCounts; var indices = UnmanagedDrawables.Masks; // Pull data. var buffer = new CubismDrawable[counts[UnmanagedIndex]]; for (var i = 0; i < buffer.Length; ++i) { for (var j = 0; j < drawables.Length; ++j) { if (drawables[j].UnmanagedIndex != indices[UnmanagedIndex][i]) { continue; } buffer[i] = drawables[j]; break; } } return buffer; } } /// /// Copy of vertex positions. /// public Vector3[] VertexPositions { get { // Get addresses. var counts = UnmanagedDrawables.VertexCounts; var positions = UnmanagedDrawables.VertexPositions; // Pull data. var buffer = new Vector3[counts[UnmanagedIndex]]; for (var i = 0; i < buffer.Length; ++i) { buffer[i] = new Vector3( positions[UnmanagedIndex][(i * 2) + 0], positions[UnmanagedIndex][(i * 2) + 1] ); } return buffer; } } /// /// Copy of vertex texture coordinates. /// public Vector2[] VertexUvs { get { // Get addresses. var counts = UnmanagedDrawables.VertexCounts; var uvs = UnmanagedDrawables.VertexUvs; // Pull data. var buffer = new Vector2[counts[UnmanagedIndex]]; for (var i = 0; i < buffer.Length; ++i) { buffer[i] = new Vector2( uvs[UnmanagedIndex][(i * 2) + 0], uvs[UnmanagedIndex][(i * 2) + 1] ); } return buffer; } } /// /// Copy of triangle indices. /// public int[] Indices { get { // Get addresses. var counts = UnmanagedDrawables.IndexCounts; var indices = UnmanagedDrawables.Indices; // Pull data. var buffer = new int[counts[UnmanagedIndex]]; for (var i = 0; i < buffer.Length; ++i) { buffer[i] = indices[UnmanagedIndex][i]; } return buffer; } } /// /// True if double-sided. /// public bool IsDoubleSided { get { // Get address. var flags = UnmanagedDrawables.ConstantFlags; // Pull data. return flags[UnmanagedIndex].HasIsDoubleSidedFlag(); } } /// /// True if masking is requested. /// public bool IsMasked { get { // Get address. var counts = UnmanagedDrawables.MaskCounts; // Pull data. return counts[UnmanagedIndex] > 0; } } /// /// True if inverted mask. /// public bool IsInverted { get { // Get address. var flags = UnmanagedDrawables.ConstantFlags; // Pull data. return flags[UnmanagedIndex].HasIsInvertedMaskFlag(); } } /// /// True if additive blending is requested. /// public bool BlendAdditive { get { // Get address. var flags = UnmanagedDrawables.ConstantFlags; // Pull data. return flags[UnmanagedIndex].HasBlendAdditiveFlag(); } } /// /// True if multiply blending is setd. /// public bool MultiplyBlend { get { // Get address. var flags = UnmanagedDrawables.ConstantFlags; // Pull data. return flags[UnmanagedIndex].HasBlendMultiplicativeFlag(); } } /// /// Revives instance. /// /// Handle to unmanaged model. internal void Revive(CubismUnmanagedModel unmanagedModel) { UnmanagedDrawables = unmanagedModel.Drawables; } /// /// Restores instance to initial state. /// /// Handle to unmanaged model. /// Position in unmanaged arrays. private void Reset(CubismUnmanagedModel unmanagedModel, int unmanagedIndex) { Revive(unmanagedModel); UnmanagedIndex = unmanagedIndex; name = Id; } } }