From 535153be6b1c089ddc1c0d1f4fd3c24d49c26341 Mon Sep 17 00:00:00 2001 From: VaDiM Date: Fri, 9 Feb 2024 22:34:08 +0300 Subject: [PATCH] Add cdi3.json support for l2d export (beta) --- .../CubismLive2DExtractor/CubismCdi3Json.cs | 35 ++++++++ .../CubismLive2DExtractor/CubismModel3Json.cs | 1 + .../CubismLive2DExtractor/CubismParsers.cs | 4 + .../CubismLive2DExtractor/Live2DExtractor.cs | 85 +++++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 AssetStudioUtility/CubismLive2DExtractor/CubismCdi3Json.cs diff --git a/AssetStudioUtility/CubismLive2DExtractor/CubismCdi3Json.cs b/AssetStudioUtility/CubismLive2DExtractor/CubismCdi3Json.cs new file mode 100644 index 0000000..42b75ca --- /dev/null +++ b/AssetStudioUtility/CubismLive2DExtractor/CubismCdi3Json.cs @@ -0,0 +1,35 @@ +using System; + +namespace CubismLive2DExtractor +{ + public class CubismCdi3Json + { + public int Version { get; set; } + public ParamGroupArray[] Parameters { get; set; } + public ParamGroupArray[] ParameterGroups { get; set; } + public PartArray[] Parts { get; set; } + + public class ParamGroupArray : IComparable + { + public string Id { get; set; } + public string GroupId { get; set; } + public string Name { get; set; } + + public int CompareTo(object obj) + { + return string.Compare(Id, ((ParamGroupArray)obj).Id, StringComparison.OrdinalIgnoreCase); + } + } + + public class PartArray : IComparable + { + public string Id { get; set; } + public string Name { get; set; } + + public int CompareTo(object obj) + { + return string.Compare(Id, ((PartArray)obj).Id, StringComparison.OrdinalIgnoreCase); + } + } + } +} diff --git a/AssetStudioUtility/CubismLive2DExtractor/CubismModel3Json.cs b/AssetStudioUtility/CubismLive2DExtractor/CubismModel3Json.cs index c3823f4..cf2ddd5 100644 --- a/AssetStudioUtility/CubismLive2DExtractor/CubismModel3Json.cs +++ b/AssetStudioUtility/CubismLive2DExtractor/CubismModel3Json.cs @@ -13,6 +13,7 @@ namespace CubismLive2DExtractor { public string Moc; public string[] Textures; + public string DisplayInfo; public string Physics; public JObject Motions; public JArray Expressions; diff --git a/AssetStudioUtility/CubismLive2DExtractor/CubismParsers.cs b/AssetStudioUtility/CubismLive2DExtractor/CubismParsers.cs index 912707e..69f3a42 100644 --- a/AssetStudioUtility/CubismLive2DExtractor/CubismParsers.cs +++ b/AssetStudioUtility/CubismLive2DExtractor/CubismParsers.cs @@ -14,6 +14,7 @@ namespace CubismLive2DExtractor FadeMotion, Expression, Physics, + DisplayInfo, } public static string ParsePhysics(OrderedDictionary physicsDict) @@ -143,6 +144,9 @@ namespace CubismLive2DExtractor case CubismMonoBehaviourType.Physics: fieldName = "_rig"; break; + case CubismMonoBehaviourType.DisplayInfo: + fieldName = "name"; + break; } if (m_Type.m_Nodes.FindIndex(x => x.m_Name.ToLower() == fieldName) < 0) { diff --git a/AssetStudioUtility/CubismLive2DExtractor/Live2DExtractor.cs b/AssetStudioUtility/CubismLive2DExtractor/Live2DExtractor.cs index d1b606b..1bdc897 100644 --- a/AssetStudioUtility/CubismLive2DExtractor/Live2DExtractor.cs +++ b/AssetStudioUtility/CubismLive2DExtractor/Live2DExtractor.cs @@ -29,6 +29,8 @@ namespace CubismLive2DExtractor private MonoBehaviour MocMono { get; set; } private MonoBehaviour PhysicsMono { get; set; } private MonoBehaviour FadeMotionLst { get; set; } + private List ParametersCdi { get; set; } + private List PartsCdi { get; set; } public Live2DExtractor(IGrouping assets, List inClipMotions = null, List inFadeMotions = null, MonoBehaviour inFadeMotionLst = null) { @@ -42,6 +44,8 @@ namespace CubismLive2DExtractor ParameterNames = new HashSet(); PartNames = new HashSet(); FadeMotionLst = inFadeMotionLst; + ParametersCdi = new List(); + PartsCdi = new List(); Logger.Info("Sorting model assets.."); foreach (var asset in assets) @@ -98,6 +102,18 @@ namespace CubismLive2DExtractor PartNames.Add(partGameObject.m_Name); } break; + case "CubismDisplayInfoParameterName": + if (m_MonoBehaviour.m_GameObject.TryGet(out _)) + { + ParametersCdi.Add(m_MonoBehaviour); + } + break; + case "CubismDisplayInfoPartName": + if (m_MonoBehaviour.m_GameObject.TryGet(out _)) + { + PartsCdi.Add(m_MonoBehaviour); + } + break; } } break; @@ -195,6 +211,59 @@ namespace CubismLive2DExtractor } #endregion + #region cdi3.json + var isCdiParsed = false; + if (ParametersCdi.Count > 0 || PartsCdi.Count > 0) + { + var cdiJson = new CubismCdi3Json + { + Version = 3, + ParameterGroups = Array.Empty() + }; + + var parameters = new SortedSet(); + foreach (var paramMono in ParametersCdi) + { + var displayName = GetDisplayName(paramMono, assemblyLoader); + if (displayName == null) + break; + + paramMono.m_GameObject.TryGet(out var paramGameObject); + var paramId = paramGameObject.m_Name; + parameters.Add(new CubismCdi3Json.ParamGroupArray + { + Id = paramId, + GroupId = "", + Name = displayName + }); + } + cdiJson.Parameters = parameters.ToArray(); + + var parts = new SortedSet(); + foreach (var partMono in PartsCdi) + { + var displayName = GetDisplayName(partMono, assemblyLoader); + if (displayName == null) + break; + + partMono.m_GameObject.TryGet(out var partGameObject); + var paramId = partGameObject.m_Name; + parts.Add(new CubismCdi3Json.PartArray + { + Id = paramId, + Name = displayName + }); + } + cdiJson.Parts = parts.ToArray(); + + if (parts.Count > 0 || parameters.Count > 0) + { + File.WriteAllText($"{destPath}{modelName}.cdi3.json", JsonConvert.SerializeObject(cdiJson, Formatting.Indented)); + isCdiParsed = true; + } + } + #endregion + #region motion3.json var motions = new SortedDictionary(); var destMotionPath = Path.Combine(destPath, "motions") + Path.DirectorySeparatorChar; @@ -330,6 +399,7 @@ namespace CubismLive2DExtractor { Moc = $"{modelName}.moc3", Textures = textures.ToArray(), + DisplayInfo = isCdiParsed ? $"{modelName}.cdi3.json" : "", Physics = PhysicsMono == null ? null : $"{modelName}.physics3.json", Motions = JObject.FromObject(motions), Expressions = expressions, @@ -399,5 +469,20 @@ namespace CubismLive2DExtractor File.WriteAllText($"{destMotionPath}{animName}.motion3.json", JsonConvert.SerializeObject(motionJson, Formatting.Indented, new MyJsonConverter())); } } + + private static string GetDisplayName(MonoBehaviour cdiMono, AssemblyLoader assemblyLoader) + { + var dict = ParseMonoBehaviour(cdiMono, CubismMonoBehaviourType.DisplayInfo, assemblyLoader); + if (dict == null) + return null; + + var name = (string)dict["Name"]; + if (dict.Contains("DisplayName")) + { + var displayName = (string)dict["DisplayName"]; + name = displayName != "" ? displayName : name; + } + return name; + } } }