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