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