/**
* 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.Framework.Physics;
using System;
using UnityEngine;
namespace Live2D.Cubism.Framework.Json
{
[Serializable]
public sealed class CubismPhysics3Json
{
///
/// Loads a physics3.json asset.
///
/// physics3.json to deserialize.
/// Deserialized physics3.json on success; otherwise.
public static CubismPhysics3Json LoadFrom(string physics3Json)
{
return (string.IsNullOrEmpty(physics3Json))
? null
: JsonUtility.FromJson(physics3Json);
}
///
/// Loads a physics3.json asset.
///
/// motion3.json to deserialize.
/// Deserialized physics3.json on success; otherwise.
public static CubismPhysics3Json LoadFrom(TextAsset physics3JsonAsset)
{
return (physics3JsonAsset == null)
? null
: LoadFrom(physics3JsonAsset.text);
}
public CubismPhysicsRig ToRig()
{
var instance = new CubismPhysicsRig();
instance.Gravity.x = Meta.EffectiveForces.Gravity.X;
instance.Gravity.y = Meta.EffectiveForces.Gravity.Y;
instance.Wind.x = Meta.EffectiveForces.Wind.X;
instance.Wind.y = Meta.EffectiveForces.Wind.Y;
instance.SubRigs = new CubismPhysicsSubRig[Meta.PhysicsSettingCount];
for (var i = 0; i < instance.SubRigs.Length; ++i)
{
instance.SubRigs[i] = new CubismPhysicsSubRig
{
Input = ReadInput(PhysicsSettings[i].Input),
Output = ReadOutput(PhysicsSettings[i].Output),
Particles = ReadParticles(PhysicsSettings[i].Vertices),
Normalization = ReadNormalization(PhysicsSettings[i].Normalization)
};
}
return instance;
}
private CubismPhysicsInput[] ReadInput(SerializableInput[] source)
{
var dataArray = new CubismPhysicsInput[source.Length];
for (var i = 0; i < dataArray.Length; ++i)
{
dataArray[i] = new CubismPhysicsInput
{
SourceId = source[i].Source.Id,
AngleScale = 0.0f,
ScaleOfTranslation = Vector2.zero,
Weight = source[i].Weight,
SourceComponent = (CubismPhysicsSourceComponent) Enum.Parse(
typeof(CubismPhysicsSourceComponent), source[i].Type
),
IsInverted = source[i].Reflect
};
}
return dataArray;
}
private CubismPhysicsOutput[] ReadOutput(SerializableOutput[] source)
{
var dataArray = new CubismPhysicsOutput[source.Length];
for (var i = 0; i < dataArray.Length; ++i)
{
dataArray[i] = new CubismPhysicsOutput
{
DestinationId = source[i].Destination.Id,
ParticleIndex = source[i].VertexIndex,
TranslationScale = Vector2.zero,
AngleScale = source[i].Scale,
Weight = source[i].Weight,
SourceComponent = (CubismPhysicsSourceComponent) Enum.Parse(
typeof(CubismPhysicsSourceComponent), source[i].Type
),
IsInverted = source[i].Reflect,
ValueBelowMinimum = 0.0f,
ValueExceededMaximum = 0.0f
};
}
return dataArray;
}
private CubismPhysicsParticle[] ReadParticles(SerializableVertex[] source)
{
var dataArray = new CubismPhysicsParticle[source.Length];
for (var i = 0; i < dataArray.Length; ++i)
{
dataArray[i] = new CubismPhysicsParticle
{
InitialPosition =
{
x = source[i].Position.X,
y = source[i].Position.Y
},
Mobility = source[i].Mobility,
Delay = source[i].Delay,
Acceleration = source[i].Acceleration,
Radius = source[i].Radius,
Position = Vector2.zero,
LastPosition = Vector2.zero,
LastGravity = Vector2.down,
Force = Vector2.zero,
Velocity = Vector2.zero
};
}
return dataArray;
}
private CubismPhysicsNormalization ReadNormalization(SerializableNormalization source)
{
return new CubismPhysicsNormalization
{
Position =
{
Maximum = source.Position.Maximum,
Minimum = source.Position.Minimum,
Default = source.Position.Default
},
Angle =
{
Maximum = source.Angle.Maximum,
Minimum = source.Angle.Minimum,
Default = source.Angle.Default
}
};
}
#region Json Data
///
/// Json file format version.
///
[SerializeField]
public int Version;
///
/// Additional data describing physics.
///
[SerializeField]
public SerializableMeta Meta;
///
/// TODO Document.
///
[SerializeField]
public SerializablePhysicsSettings[] PhysicsSettings;
#endregion
#region Json Helpers
///
/// 2-component vector.
///
[Serializable]
public struct SerializableVector2
{
[SerializeField]
public float X;
[SerializeField]
public float Y;
}
///
/// TODO Document.
///
[Serializable]
public struct SerializableNormalizationValue
{
///
/// Minimum of normalization.
///
[SerializeField]
public float Minimum;
///
/// Center of normalization range.
///
[SerializeField]
public float Default;
///
/// Maximum of normalization.
///
[SerializeField]
public float Maximum;
}
///
/// Target parameter of model.
///
[Serializable]
public struct SerializableParameter
{
///
/// Target type.
///
[SerializeField]
public string Target;
///
/// Parameter ID.
///
[SerializeField]
public string Id;
}
///
/// TODO Document.
///
[Serializable]
public struct SerializableInput
{
///
/// Target parameter.
///
[SerializeField]
public SerializableParameter Source;
///
/// Influence ratio of each kind.
///
[SerializeField]
public float Weight;
///
/// Type of source.
///
[SerializeField]
public string Type;
///
/// TODO Document.
///
[SerializeField]
public bool Reflect;
}
///
/// TODO Document.
///
[Serializable]
public struct SerializableOutput
{
///
/// Target parameter.
///
[SerializeField]
public SerializableParameter Destination;
///
/// Index of referenced vertex.
///
[SerializeField]
public int VertexIndex;
///
/// Scale.
///
[SerializeField]
public float Scale;
///
/// Influence ratio of each kind.
///
[SerializeField]
public float Weight;
///
/// Type of destination.
///
[SerializeField]
public string Type;
///
/// TODO Document.
///
[SerializeField]
public bool Reflect;
}
///
/// Single vertex.
///
[Serializable]
public struct SerializableVertex
{
///
/// Default position.
///
[SerializeField]
public SerializableVector2 Position;
///
/// Mobility.
///
[SerializeField]
public float Mobility;
///
/// Delay ratio.
///
[SerializeField]
public float Delay;
///
/// Acceleration.
///
[SerializeField]
public float Acceleration;
///
/// Length.
///
[SerializeField]
public float Radius;
}
///
/// TODO Document.
///
[Serializable]
public struct SerializableNormalization
{
///
/// Normalization value of position.
///
[SerializeField]
public SerializableNormalizationValue Position;
///
/// Normalization value of angle.
///
[SerializeField]
public SerializableNormalizationValue Angle;
}
///
/// Setting of physics calculation.
///
[Serializable]
public struct SerializablePhysicsSettings
{
///
/// TODO Document.
///
[SerializeField]
public string Id;
///
/// Input array.
///
[SerializeField]
public SerializableInput[] Input;
///
/// Output array.
///
[SerializeField]
public SerializableOutput[] Output;
///
/// Vertices.
///
[SerializeField]
public SerializableVertex[] Vertices;
///
/// Normalization parameter of using input.
///
[SerializeField]
public SerializableNormalization Normalization;
}
///
/// Additional data describing physics.
///
[Serializable]
public struct SerializableMeta
{
///
/// Number of physics settings.
///
[SerializeField]
public int PhysicsSettingCount;
///
/// Total number of input parameters.
///
[SerializeField]
public int TotalInputCount;
///
/// Total number of output parameters.
///
[SerializeField]
public int TotalOutputCount;
///
/// Total number of vertices.
///
[SerializeField]
public int TotalVertexCount;
///
/// TODO Document.
///
[SerializeField]
public SerializableEffectiveForces EffectiveForces;
}
///
/// TODO Document.
///
[Serializable]
public struct SerializableEffectiveForces
{
///
/// Gravity.
///
[SerializeField]
public SerializableVector2 Gravity;
///
/// Wind. (Not in use)
///
[SerializeField]
public SerializableVector2 Wind;
}
#endregion
}
}