mirror of
https://github.com/aelurum/AssetStudio.git
synced 2025-05-25 05:40:21 -04:00
Some fixes for Live2D export
This commit is contained in:
parent
45bf9251c9
commit
e415740373
@ -624,6 +624,7 @@ namespace AssetStudioCLI
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}).Select(x => x.Asset).ToArray();
|
}).Select(x => x.Asset).ToArray();
|
||||||
|
|
||||||
if (cubismMocs.Length == 0)
|
if (cubismMocs.Length == 0)
|
||||||
{
|
{
|
||||||
Logger.Default.Log(LoggerEvent.Info, "Live2D Cubism models were not found.", ignoreLevel: true);
|
Logger.Default.Log(LoggerEvent.Info, "Live2D Cubism models were not found.", ignoreLevel: true);
|
||||||
@ -631,7 +632,18 @@ namespace AssetStudioCLI
|
|||||||
}
|
}
|
||||||
if (cubismMocs.Length > 1)
|
if (cubismMocs.Length > 1)
|
||||||
{
|
{
|
||||||
var basePathSet = cubismMocs.Select(x => containers[x].Substring(0, containers[x].LastIndexOf("/"))).ToHashSet();
|
var basePathSet = cubismMocs.Select(x =>
|
||||||
|
{
|
||||||
|
var pathLen = containers.TryGetValue(x, out var itemContainer) ? itemContainer.LastIndexOf("/") : 0;
|
||||||
|
pathLen = pathLen < 0 ? containers[x].Length : pathLen;
|
||||||
|
return itemContainer?.Substring(0, pathLen);
|
||||||
|
}).ToHashSet();
|
||||||
|
|
||||||
|
if (basePathSet.All(x => x == null))
|
||||||
|
{
|
||||||
|
Logger.Error($"Live2D Cubism export error: Cannot find any model related files.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (basePathSet.Count != cubismMocs.Length)
|
if (basePathSet.Count != cubismMocs.Length)
|
||||||
{
|
{
|
||||||
@ -639,9 +651,16 @@ namespace AssetStudioCLI
|
|||||||
Logger.Debug($"useFullContainerPath: {useFullContainerPath}");
|
Logger.Debug($"useFullContainerPath: {useFullContainerPath}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var basePathList = useFullContainerPath ?
|
|
||||||
cubismMocs.Select(x => containers[x]).ToList() :
|
var basePathList = cubismMocs.Select(x =>
|
||||||
cubismMocs.Select(x => containers[x].Substring(0, containers[x].LastIndexOf("/"))).ToList();
|
{
|
||||||
|
containers.TryGetValue(x, out var container);
|
||||||
|
container = useFullContainerPath
|
||||||
|
? container
|
||||||
|
: container?.Substring(0, container.LastIndexOf("/"));
|
||||||
|
return container;
|
||||||
|
}).Where(x => x != null).ToList();
|
||||||
|
|
||||||
var lookup = containers.ToLookup(
|
var lookup = containers.ToLookup(
|
||||||
x => basePathList.Find(b => x.Value.Contains(b) && x.Value.Split('/').Any(y => y == b.Substring(b.LastIndexOf("/") + 1))),
|
x => basePathList.Find(b => x.Value.Contains(b) && x.Value.Split('/').Any(y => y == b.Substring(b.LastIndexOf("/") + 1))),
|
||||||
x => x.Key
|
x => x.Key
|
||||||
@ -649,16 +668,15 @@ namespace AssetStudioCLI
|
|||||||
|
|
||||||
var totalModelCount = lookup.LongCount(x => x.Key != null);
|
var totalModelCount = lookup.LongCount(x => x.Key != null);
|
||||||
Logger.Info($"Found {totalModelCount} model(s).");
|
Logger.Info($"Found {totalModelCount} model(s).");
|
||||||
var name = "";
|
|
||||||
var modelCounter = 0;
|
var modelCounter = 0;
|
||||||
foreach (var assets in lookup)
|
foreach (var assets in lookup)
|
||||||
{
|
{
|
||||||
var container = assets.Key;
|
var srcContainer = assets.Key;
|
||||||
if (container == null)
|
if (srcContainer == null)
|
||||||
continue;
|
continue;
|
||||||
name = container;
|
var container = srcContainer;
|
||||||
|
|
||||||
Logger.Info($"[{modelCounter + 1}/{totalModelCount}] Exporting Live2D: \"{container.Color(Ansi.BrightCyan)}\"");
|
Logger.Info($"[{modelCounter + 1}/{totalModelCount}] Exporting Live2D: \"{srcContainer.Color(Ansi.BrightCyan)}\"");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var modelName = useFullContainerPath ? Path.GetFileNameWithoutExtension(container) : container.Substring(container.LastIndexOf('/') + 1);
|
var modelName = useFullContainerPath ? Path.GetFileNameWithoutExtension(container) : container.Substring(container.LastIndexOf('/') + 1);
|
||||||
@ -670,10 +688,11 @@ namespace AssetStudioCLI
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.Error($"Live2D model export error: \"{name}\"", ex);
|
Logger.Error($"Live2D model export error: \"{srcContainer}\"", ex);
|
||||||
}
|
}
|
||||||
Progress.Report(modelCounter, (int)totalModelCount);
|
Progress.Report(modelCounter, (int)totalModelCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
var status = modelCounter > 0 ?
|
var status = modelCounter > 0 ?
|
||||||
$"Finished exporting [{modelCounter}/{totalModelCount}] Live2D model(s) to \"{CLIOptions.o_outputFolder.Value.Color(Ansi.BrightCyan)}\"" :
|
$"Finished exporting [{modelCounter}/{totalModelCount}] Live2D model(s) to \"{CLIOptions.o_outputFolder.Value.Color(Ansi.BrightCyan)}\"" :
|
||||||
"Nothing exported.";
|
"Nothing exported.";
|
||||||
|
@ -259,6 +259,7 @@ namespace AssetStudioGUI
|
|||||||
Progress.Report(++i, objectCount);
|
Progress.Report(++i, objectCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
allContainers.Clear();
|
||||||
foreach ((var pptr, var container) in containers)
|
foreach ((var pptr, var container) in containers)
|
||||||
{
|
{
|
||||||
if (pptr.TryGet(out var obj))
|
if (pptr.TryGet(out var obj))
|
||||||
@ -753,32 +754,51 @@ namespace AssetStudioGUI
|
|||||||
var useFullContainerPath = false;
|
var useFullContainerPath = false;
|
||||||
if (cubismMocs.Length > 1)
|
if (cubismMocs.Length > 1)
|
||||||
{
|
{
|
||||||
var basePathSet = cubismMocs.Select(x => allContainers[x].Substring(0, allContainers[x].LastIndexOf("/"))).ToHashSet();
|
var basePathSet = cubismMocs.Select(x =>
|
||||||
|
{
|
||||||
|
var pathLen = allContainers.TryGetValue(x, out var itemContainer) ? itemContainer.LastIndexOf("/") : 0;
|
||||||
|
pathLen = pathLen < 0 ? allContainers[x].Length : pathLen;
|
||||||
|
return itemContainer?.Substring(0, pathLen);
|
||||||
|
}).ToHashSet();
|
||||||
|
|
||||||
|
if (basePathSet.All(x => x == null))
|
||||||
|
{
|
||||||
|
Logger.Error($"Live2D Cubism export error\r\nCannot find any model related files");
|
||||||
|
StatusStripUpdate("Live2D export canceled");
|
||||||
|
Progress.Reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (basePathSet.Count != cubismMocs.Length)
|
if (basePathSet.Count != cubismMocs.Length)
|
||||||
{
|
{
|
||||||
useFullContainerPath = true;
|
useFullContainerPath = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var basePathList = useFullContainerPath ?
|
|
||||||
cubismMocs.Select(x => allContainers[x]).ToList() :
|
var basePathList = cubismMocs.Select(x =>
|
||||||
cubismMocs.Select(x => allContainers[x].Substring(0, allContainers[x].LastIndexOf("/"))).ToList();
|
{
|
||||||
|
allContainers.TryGetValue(x, out var container);
|
||||||
|
container = useFullContainerPath
|
||||||
|
? container
|
||||||
|
: container?.Substring(0, container.LastIndexOf("/"));
|
||||||
|
return container;
|
||||||
|
}).Where(x => x != null).ToList();
|
||||||
|
|
||||||
var lookup = allContainers.ToLookup(
|
var lookup = allContainers.ToLookup(
|
||||||
x => basePathList.Find(b => x.Value.Contains(b) && x.Value.Split('/').Any(y => y == b.Substring(b.LastIndexOf("/") + 1))),
|
x => basePathList.Find(b => x.Value.Contains(b) && x.Value.Split('/').Any(y => y == b.Substring(b.LastIndexOf("/") + 1))),
|
||||||
x => x.Key
|
x => x.Key
|
||||||
);
|
);
|
||||||
|
|
||||||
var totalModelCount = lookup.LongCount(x => x.Key != null);
|
var totalModelCount = lookup.LongCount(x => x.Key != null);
|
||||||
var name = "";
|
|
||||||
var modelCounter = 0;
|
var modelCounter = 0;
|
||||||
foreach (var assets in lookup)
|
foreach (var assets in lookup)
|
||||||
{
|
{
|
||||||
var container = assets.Key;
|
var srcContainer = assets.Key;
|
||||||
if (container == null)
|
if (srcContainer == null)
|
||||||
continue;
|
continue;
|
||||||
name = container;
|
var container = srcContainer;
|
||||||
|
|
||||||
Logger.Info($"[{modelCounter + 1}/{totalModelCount}] Exporting Live2D: \"{container}\"...");
|
Logger.Info($"[{modelCounter + 1}/{totalModelCount}] Exporting Live2D: \"{srcContainer}\"...");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var modelName = useFullContainerPath ? Path.GetFileNameWithoutExtension(container) : container.Substring(container.LastIndexOf('/') + 1);
|
var modelName = useFullContainerPath ? Path.GetFileNameWithoutExtension(container) : container.Substring(container.LastIndexOf('/') + 1);
|
||||||
@ -790,11 +810,17 @@ namespace AssetStudioGUI
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.Error($"Live2D model export error: \"{name}\"", ex);
|
Logger.Error($"Live2D model export error: \"{srcContainer}\"", ex);
|
||||||
}
|
}
|
||||||
Progress.Report(modelCounter, (int)totalModelCount);
|
Progress.Report(modelCounter, (int)totalModelCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Info($"Finished exporting [{modelCounter}/{totalModelCount}] Live2D model(s).");
|
Logger.Info($"Finished exporting [{modelCounter}/{totalModelCount}] Live2D model(s).");
|
||||||
|
if (modelCounter < totalModelCount)
|
||||||
|
{
|
||||||
|
var total = (int)totalModelCount;
|
||||||
|
Progress.Report(total, total);
|
||||||
|
}
|
||||||
if (Properties.Settings.Default.openAfterExport && modelCounter > 0)
|
if (Properties.Settings.Default.openAfterExport && modelCounter > 0)
|
||||||
{
|
{
|
||||||
OpenFolderInExplorer(exportPath);
|
OpenFolderInExplorer(exportPath);
|
||||||
|
@ -26,20 +26,57 @@ namespace CubismLive2DExtractor
|
|||||||
Directory.CreateDirectory(destPath);
|
Directory.CreateDirectory(destPath);
|
||||||
Directory.CreateDirectory(destTexturePath);
|
Directory.CreateDirectory(destTexturePath);
|
||||||
|
|
||||||
var monoBehaviours = new List<MonoBehaviour>();
|
var expressionList = new List<MonoBehaviour>();
|
||||||
var texture2Ds = new List<Texture2D>();
|
|
||||||
var gameObjects = new List<GameObject>();
|
var gameObjects = new List<GameObject>();
|
||||||
var animationClips = new List<AnimationClip>();
|
var animationClips = new List<AnimationClip>();
|
||||||
|
|
||||||
|
var textures = new SortedSet<string>();
|
||||||
|
var eyeBlinkParameters = new HashSet<string>();
|
||||||
|
var lipSyncParameters = new HashSet<string>();
|
||||||
|
MonoBehaviour physics = null;
|
||||||
|
|
||||||
foreach (var asset in assets)
|
foreach (var asset in assets)
|
||||||
{
|
{
|
||||||
switch (asset)
|
switch (asset)
|
||||||
{
|
{
|
||||||
case MonoBehaviour m_MonoBehaviour:
|
case MonoBehaviour m_MonoBehaviour:
|
||||||
monoBehaviours.Add(m_MonoBehaviour);
|
if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))
|
||||||
|
{
|
||||||
|
switch (m_Script.m_ClassName)
|
||||||
|
{
|
||||||
|
case "CubismMoc":
|
||||||
|
File.WriteAllBytes($"{destPath}{modelName}.moc3", ParseMoc(m_MonoBehaviour)); //moc
|
||||||
|
break;
|
||||||
|
case "CubismPhysicsController":
|
||||||
|
physics = physics ?? m_MonoBehaviour;
|
||||||
|
break;
|
||||||
|
case "CubismExpressionData":
|
||||||
|
expressionList.Add(m_MonoBehaviour);
|
||||||
|
break;
|
||||||
|
case "CubismEyeBlinkParameter":
|
||||||
|
if (m_MonoBehaviour.m_GameObject.TryGet(out var blinkGameObject))
|
||||||
|
{
|
||||||
|
eyeBlinkParameters.Add(blinkGameObject.m_Name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "CubismMouthParameter":
|
||||||
|
if (m_MonoBehaviour.m_GameObject.TryGet(out var mouthGameObject))
|
||||||
|
{
|
||||||
|
lipSyncParameters.Add(mouthGameObject.m_Name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Texture2D m_Texture2D:
|
case Texture2D m_Texture2D:
|
||||||
texture2Ds.Add(m_Texture2D);
|
using (var image = m_Texture2D.ConvertToImage(flip: true))
|
||||||
|
{
|
||||||
|
using (var file = File.OpenWrite($"{destTexturePath}{m_Texture2D.m_Name}.png"))
|
||||||
|
{
|
||||||
|
image.WriteToStream(file, ImageFormat.Png);
|
||||||
|
}
|
||||||
|
textures.Add($"textures/{m_Texture2D.m_Name}.png"); //texture
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GameObject m_GameObject:
|
case GameObject m_GameObject:
|
||||||
gameObjects.Add(m_GameObject);
|
gameObjects.Add(m_GameObject);
|
||||||
@ -50,15 +87,12 @@ namespace CubismLive2DExtractor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//physics
|
if (textures.Count == 0)
|
||||||
var physics = monoBehaviours.FirstOrDefault(x =>
|
|
||||||
{
|
{
|
||||||
if (x.m_Script.TryGet(out var m_Script))
|
Logger.Warning($"No textures found for \"{modelName}\" model.");
|
||||||
{
|
}
|
||||||
return m_Script.m_ClassName == "CubismPhysicsController";
|
|
||||||
}
|
//physics
|
||||||
return false;
|
|
||||||
});
|
|
||||||
if (physics != null)
|
if (physics != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -73,31 +107,6 @@ namespace CubismLive2DExtractor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//moc
|
|
||||||
var moc = monoBehaviours.First(x =>
|
|
||||||
{
|
|
||||||
if (x.m_Script.TryGet(out var m_Script))
|
|
||||||
{
|
|
||||||
return m_Script.m_ClassName == "CubismMoc";
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
File.WriteAllBytes($"{destPath}{modelName}.moc3", ParseMoc(moc));
|
|
||||||
|
|
||||||
//texture
|
|
||||||
var textures = new SortedSet<string>();
|
|
||||||
foreach (var texture2D in texture2Ds)
|
|
||||||
{
|
|
||||||
using (var image = texture2D.ConvertToImage(flip: true))
|
|
||||||
{
|
|
||||||
textures.Add($"textures/{texture2D.m_Name}.png");
|
|
||||||
using (var file = File.OpenWrite($"{destTexturePath}{texture2D.m_Name}.png"))
|
|
||||||
{
|
|
||||||
image.WriteToStream(file, ImageFormat.Png);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//motion
|
//motion
|
||||||
var motions = new SortedDictionary<string, JArray>();
|
var motions = new SortedDictionary<string, JArray>();
|
||||||
|
|
||||||
@ -205,23 +214,30 @@ namespace CubismLive2DExtractor
|
|||||||
}
|
}
|
||||||
json.Meta.TotalUserDataSize = totalUserDataSize;
|
json.Meta.TotalUserDataSize = totalUserDataSize;
|
||||||
|
|
||||||
var motionPath = new JObject(new JProperty("File", $"motions/{animation.Name}.motion3.json"));
|
var animName = animation.Name;
|
||||||
motions.Add(animation.Name, new JArray(motionPath));
|
if (motions.ContainsKey(animName))
|
||||||
File.WriteAllText($"{destMotionPath}{animation.Name}.motion3.json", JsonConvert.SerializeObject(json, Formatting.Indented, new MyJsonConverter()));
|
{
|
||||||
|
animName = $"{animName}_{animation.GetHashCode()}";
|
||||||
|
if (motions.ContainsKey(animName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var motionPath = new JObject(new JProperty("File", $"motions/{animName}.motion3.json"));
|
||||||
|
motions.Add(animName, new JArray(motionPath));
|
||||||
|
File.WriteAllText($"{destMotionPath}{animName}.motion3.json", JsonConvert.SerializeObject(json, Formatting.Indented, new MyJsonConverter()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//expression
|
//expression
|
||||||
var expressions = new JArray();
|
var expressions = new JArray();
|
||||||
var monoBehaviourArray = monoBehaviours.Where(x => x.m_Name.EndsWith(".exp3")).ToArray();
|
if (expressionList.Count > 0)
|
||||||
if (monoBehaviourArray.Length > 0)
|
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(destExpressionPath);
|
Directory.CreateDirectory(destExpressionPath);
|
||||||
}
|
}
|
||||||
foreach (var monoBehaviour in monoBehaviourArray)
|
foreach (var monoBehaviour in expressionList)
|
||||||
{
|
{
|
||||||
var fullName = monoBehaviour.m_Name;
|
var expressionName = monoBehaviour.m_Name.Replace(".exp3", "");
|
||||||
var expressionName = fullName.Replace(".exp3", "");
|
|
||||||
var expressionObj = monoBehaviour.ToType();
|
var expressionObj = monoBehaviour.ToType();
|
||||||
if (expressionObj == null)
|
if (expressionObj == null)
|
||||||
{
|
{
|
||||||
@ -238,57 +254,38 @@ namespace CubismLive2DExtractor
|
|||||||
expressions.Add(new JObject
|
expressions.Add(new JObject
|
||||||
{
|
{
|
||||||
{ "Name", expressionName },
|
{ "Name", expressionName },
|
||||||
{ "File", $"expressions/{fullName}.json" }
|
{ "File", $"expressions/{expressionName}.exp3.json" }
|
||||||
});
|
});
|
||||||
File.WriteAllText($"{destExpressionPath}{fullName}.json", JsonConvert.SerializeObject(expression, Formatting.Indented));
|
File.WriteAllText($"{destExpressionPath}{expressionName}.exp3.json", JsonConvert.SerializeObject(expression, Formatting.Indented));
|
||||||
}
|
}
|
||||||
|
|
||||||
//model
|
//group
|
||||||
var groups = new List<CubismModel3Json.SerializableGroup>();
|
var groups = new List<CubismModel3Json.SerializableGroup>();
|
||||||
|
|
||||||
var eyeBlinkParameters = monoBehaviours.Where(x =>
|
//Try looking for group IDs among the gameObjects
|
||||||
{
|
|
||||||
x.m_Script.TryGet(out var m_Script);
|
|
||||||
return m_Script?.m_ClassName == "CubismEyeBlinkParameter";
|
|
||||||
}).Select(x =>
|
|
||||||
{
|
|
||||||
x.m_GameObject.TryGet(out var m_GameObject);
|
|
||||||
return m_GameObject?.m_Name;
|
|
||||||
}).ToHashSet();
|
|
||||||
if (eyeBlinkParameters.Count == 0)
|
if (eyeBlinkParameters.Count == 0)
|
||||||
{
|
{
|
||||||
eyeBlinkParameters = gameObjects.Where(x =>
|
eyeBlinkParameters = gameObjects.Where(x =>
|
||||||
{
|
x.m_Name.ToLower().Contains("eye")
|
||||||
return x.m_Name.ToLower().Contains("eye")
|
|
||||||
&& x.m_Name.ToLower().Contains("open")
|
&& x.m_Name.ToLower().Contains("open")
|
||||||
&& (x.m_Name.ToLower().Contains('l') || x.m_Name.ToLower().Contains('r'));
|
&& (x.m_Name.ToLower().Contains('l') || x.m_Name.ToLower().Contains('r'))
|
||||||
}).Select(x => x.m_Name).ToHashSet();
|
).Select(x => x.m_Name).ToHashSet();
|
||||||
}
|
}
|
||||||
|
if (lipSyncParameters.Count == 0)
|
||||||
|
{
|
||||||
|
lipSyncParameters = gameObjects.Where(x =>
|
||||||
|
x.m_Name.ToLower().Contains("mouth")
|
||||||
|
&& x.m_Name.ToLower().Contains("open")
|
||||||
|
&& x.m_Name.ToLower().Contains('y')
|
||||||
|
).Select(x => x.m_Name).ToHashSet();
|
||||||
|
}
|
||||||
|
|
||||||
groups.Add(new CubismModel3Json.SerializableGroup
|
groups.Add(new CubismModel3Json.SerializableGroup
|
||||||
{
|
{
|
||||||
Target = "Parameter",
|
Target = "Parameter",
|
||||||
Name = "EyeBlink",
|
Name = "EyeBlink",
|
||||||
Ids = eyeBlinkParameters.ToArray()
|
Ids = eyeBlinkParameters.ToArray()
|
||||||
});
|
});
|
||||||
|
|
||||||
var lipSyncParameters = monoBehaviours.Where(x =>
|
|
||||||
{
|
|
||||||
x.m_Script.TryGet(out var m_Script);
|
|
||||||
return m_Script?.m_ClassName == "CubismMouthParameter";
|
|
||||||
}).Select(x =>
|
|
||||||
{
|
|
||||||
x.m_GameObject.TryGet(out var m_GameObject);
|
|
||||||
return m_GameObject?.m_Name;
|
|
||||||
}).ToHashSet();
|
|
||||||
if (lipSyncParameters.Count == 0)
|
|
||||||
{
|
|
||||||
lipSyncParameters = gameObjects.Where(x =>
|
|
||||||
{
|
|
||||||
return x.m_Name.ToLower().Contains("mouth")
|
|
||||||
&& x.m_Name.ToLower().Contains("open")
|
|
||||||
&& x.m_Name.ToLower().Contains('y');
|
|
||||||
}).Select(x => x.m_Name).ToHashSet();
|
|
||||||
}
|
|
||||||
groups.Add(new CubismModel3Json.SerializableGroup
|
groups.Add(new CubismModel3Json.SerializableGroup
|
||||||
{
|
{
|
||||||
Target = "Parameter",
|
Target = "Parameter",
|
||||||
@ -296,6 +293,7 @@ namespace CubismLive2DExtractor
|
|||||||
Ids = lipSyncParameters.ToArray()
|
Ids = lipSyncParameters.ToArray()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//model
|
||||||
var model3 = new CubismModel3Json
|
var model3 = new CubismModel3Json
|
||||||
{
|
{
|
||||||
Version = 3,
|
Version = 3,
|
||||||
|
Loading…
Reference in New Issue
Block a user