/**
* 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;
}
}
}