[CLI] Add Animator export

This commit is contained in:
VaDiM
2025-06-07 23:45:45 +03:00
parent 60426a4b9a
commit 12799da395
5 changed files with 355 additions and 212 deletions

View File

@ -79,6 +79,18 @@ namespace AssetStudio
{
filteredAssetTypesList.Add(ClassIDType.AnimatorController);
filteredAssetTypesList.Add(ClassIDType.AnimatorOverrideController);
filteredAssetTypesList.Add(ClassIDType.Animation);
filteredAssetTypesList.Add(ClassIDType.AnimationClip);
filteredAssetTypesList.Add(ClassIDType.Avatar);
filteredAssetTypesList.Add(ClassIDType.Material);
filteredAssetTypesList.Add(ClassIDType.MeshFilter);
filteredAssetTypesList.Add(ClassIDType.MeshRenderer);
filteredAssetTypesList.Add(ClassIDType.SkinnedMeshRenderer);
}
if (classIDTypes.Contains(ClassIDType.AnimatorController))
{
filteredAssetTypesList.Add(ClassIDType.Animator);
filteredAssetTypesList.Add(ClassIDType.AnimatorOverrideController);
}
filteredAssetTypesList.UnionWith(classIDTypes);

View File

@ -10,199 +10,6 @@ namespace AssetStudioCLI
{
internal static class Exporter
{
public static bool ExportVideoClip(AssetItem item, string exportPath)
{
var m_VideoClip = (VideoClip)item.Asset;
if (m_VideoClip.m_ExternalResources.m_Size > 0)
{
if (!TryExportFile(exportPath, item, Path.GetExtension(m_VideoClip.m_OriginalPath), out var exportFullPath))
return false;
if (CLIOptions.o_logLevel.Value <= LoggerEvent.Debug)
{
var sb = new StringBuilder();
sb.AppendLine($"VideoClip format: {m_VideoClip.m_Format}");
sb.AppendLine($"VideoClip width: {m_VideoClip.Width}");
sb.AppendLine($"VideoClip height: {m_VideoClip.Height}");
sb.AppendLine($"VideoClip frame rate: {m_VideoClip.m_FrameRate:.0##}");
sb.AppendLine($"VideoClip split alpha: {m_VideoClip.m_HasSplitAlpha}");
Logger.Debug(sb.ToString());
}
m_VideoClip.m_VideoData.WriteData(exportFullPath);
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
return false;
}
public static bool ExportMovieTexture(AssetItem item, string exportPath)
{
var m_MovieTexture = (MovieTexture)item.Asset;
if (!TryExportFile(exportPath, item, ".ogv", out var exportFullPath))
return false;
File.WriteAllBytes(exportFullPath, m_MovieTexture.m_MovieData);
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
public static bool ExportShader(AssetItem item, string exportPath)
{
if (!TryExportFile(exportPath, item, ".shader", out var exportFullPath))
return false;
var m_Shader = (Shader)item.Asset;
var str = m_Shader.Convert();
File.WriteAllText(exportFullPath, str);
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
public static bool ExportTextAsset(AssetItem item, string exportPath)
{
var m_TextAsset = (TextAsset)item.Asset;
var extension = ".txt";
var assetExtension = Path.GetExtension(m_TextAsset.m_Name);
if (!CLIOptions.f_notRestoreExtensionName.Value)
{
if (!string.IsNullOrEmpty(assetExtension))
{
extension = "";
}
else if (!string.IsNullOrEmpty(item.Container))
{
var ext = Path.GetExtension(item.Container);
if (!string.IsNullOrEmpty(item.Container))
{
extension = ext;
}
}
}
if (!TryExportFile(exportPath, item, extension, out var exportFullPath))
return false;
File.WriteAllBytes(exportFullPath, m_TextAsset.m_Script);
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
public static bool ExportMonoBehaviour(AssetItem item, string exportPath)
{
if (!TryExportFile(exportPath, item, ".json", out var exportFullPath))
return false;
var m_MonoBehaviour = (MonoBehaviour)item.Asset;
var type = m_MonoBehaviour.ToType();
if (type == null)
{
var m_Type = m_MonoBehaviour.ConvertToTypeTree(Studio.assemblyLoader);
type = m_MonoBehaviour.ToType(m_Type);
}
if (type != null)
{
var str = JsonConvert.SerializeObject(type, Formatting.Indented);
File.WriteAllText(exportFullPath, str);
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
return false;
}
public static bool ExportFont(AssetItem item, string exportPath)
{
var m_Font = (Font)item.Asset;
if (m_Font.m_FontData != null)
{
var extension = ".ttf";
if (m_Font.m_FontData[0] == 79 && m_Font.m_FontData[1] == 84 && m_Font.m_FontData[2] == 84 && m_Font.m_FontData[3] == 79)
{
extension = ".otf";
}
if (!TryExportFile(exportPath, item, extension, out var exportFullPath))
return false;
File.WriteAllBytes(exportFullPath, m_Font.m_FontData);
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
return false;
}
public static void ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
{
var convert = animationList != null
? new ModelConverter(gameObject, CLIOptions.o_imageFormat.Value, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
: new ModelConverter(gameObject, CLIOptions.o_imageFormat.Value);
exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx";
ExportFbx(convert, exportPath);
}
private static void ExportFbx(IImported convert, string exportPath)
{
var fbxSettings = new Fbx.Settings
{
BoneSize = CLIOptions.o_fbxBoneSize.Value,
ScaleFactor = CLIOptions.o_fbxScaleFactor.Value,
ExportAllUvsAsDiffuseMaps = CLIOptions.f_fbxUvsAsDiffuseMaps.Value,
};
ModelExporter.ExportFbx(exportPath, convert, fbxSettings);
}
public static bool ExportRawFile(AssetItem item, string exportPath)
{
if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath, mode: "ExportRaw"))
return false;
switch (item.Asset)
{
case Texture2D m_Texture2D:
if (!string.IsNullOrEmpty(m_Texture2D.m_StreamData?.path))
{
m_Texture2D.image_data.WriteData(exportFullPath.Replace(".dat", "_data.dat"));
}
break;
case AudioClip m_AudioClip:
if (!string.IsNullOrEmpty(m_AudioClip.m_Source))
{
m_AudioClip.m_AudioData.WriteData(exportFullPath.Replace(".dat", "_data.dat"));
}
break;
case VideoClip m_VideoClip:
if (!string.IsNullOrEmpty(m_VideoClip.m_ExternalResources.m_Source))
{
m_VideoClip.m_VideoData.WriteData(exportFullPath.Replace(".dat", "_data.dat"));
}
break;
}
File.WriteAllBytes(exportFullPath, item.Asset.GetRawData());
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
public static bool ExportDumpFile(AssetItem item, string exportPath)
{
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath, mode: "Dump"))
return false;
var str = item.Asset.Dump();
if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)
{
var m_Type = m_MonoBehaviour.ConvertToTypeTree(Studio.assemblyLoader);
str = m_MonoBehaviour.Dump(m_Type);
}
if (string.IsNullOrEmpty(str))
{
str = item.Asset.DumpObject();
}
if (str != null)
{
File.WriteAllText(exportFullPath, str);
Logger.Debug($"{item.TypeString} \"{item.Text}\" saved to \"{exportFullPath}\"");
return true;
}
return false;
}
private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath, string mode = "Export")
{
var fileName = FixFileName(item.Text);
@ -235,6 +42,125 @@ namespace AssetStudioCLI
return false;
}
private static bool ExportVideoClip(AssetItem item, string exportPath)
{
var m_VideoClip = (VideoClip)item.Asset;
if (m_VideoClip.m_ExternalResources.m_Size > 0)
{
if (!TryExportFile(exportPath, item, Path.GetExtension(m_VideoClip.m_OriginalPath), out var exportFullPath))
return false;
if (CLIOptions.o_logLevel.Value <= LoggerEvent.Debug)
{
var sb = new StringBuilder();
sb.AppendLine($"VideoClip format: {m_VideoClip.m_Format}");
sb.AppendLine($"VideoClip width: {m_VideoClip.Width}");
sb.AppendLine($"VideoClip height: {m_VideoClip.Height}");
sb.AppendLine($"VideoClip frame rate: {m_VideoClip.m_FrameRate:.0##}");
sb.AppendLine($"VideoClip split alpha: {m_VideoClip.m_HasSplitAlpha}");
Logger.Debug(sb.ToString());
}
m_VideoClip.m_VideoData.WriteData(exportFullPath);
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
return false;
}
private static bool ExportMovieTexture(AssetItem item, string exportPath)
{
var m_MovieTexture = (MovieTexture)item.Asset;
if (!TryExportFile(exportPath, item, ".ogv", out var exportFullPath))
return false;
File.WriteAllBytes(exportFullPath, m_MovieTexture.m_MovieData);
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
private static bool ExportShader(AssetItem item, string exportPath)
{
if (!TryExportFile(exportPath, item, ".shader", out var exportFullPath))
return false;
var m_Shader = (Shader)item.Asset;
var str = m_Shader.Convert();
File.WriteAllText(exportFullPath, str);
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
private static bool ExportTextAsset(AssetItem item, string exportPath)
{
var m_TextAsset = (TextAsset)item.Asset;
var extension = ".txt";
var assetExtension = Path.GetExtension(m_TextAsset.m_Name);
if (!CLIOptions.f_notRestoreExtensionName.Value)
{
if (!string.IsNullOrEmpty(assetExtension))
{
extension = "";
}
else if (!string.IsNullOrEmpty(item.Container))
{
var ext = Path.GetExtension(item.Container);
if (!string.IsNullOrEmpty(item.Container))
{
extension = ext;
}
}
}
if (!TryExportFile(exportPath, item, extension, out var exportFullPath))
return false;
File.WriteAllBytes(exportFullPath, m_TextAsset.m_Script);
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
private static bool ExportMonoBehaviour(AssetItem item, string exportPath)
{
if (!TryExportFile(exportPath, item, ".json", out var exportFullPath))
return false;
var m_MonoBehaviour = (MonoBehaviour)item.Asset;
var type = m_MonoBehaviour.ToType();
if (type == null)
{
var m_Type = m_MonoBehaviour.ConvertToTypeTree(Studio.assemblyLoader);
type = m_MonoBehaviour.ToType(m_Type);
}
if (type != null)
{
var str = JsonConvert.SerializeObject(type, Formatting.Indented);
File.WriteAllText(exportFullPath, str);
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
return false;
}
private static bool ExportFont(AssetItem item, string exportPath)
{
var m_Font = (Font)item.Asset;
if (m_Font.m_FontData != null)
{
var extension = ".ttf";
if (m_Font.m_FontData[0] == 79 && m_Font.m_FontData[1] == 84 && m_Font.m_FontData[2] == 84 && m_Font.m_FontData[3] == 79)
{
extension = ".otf";
}
if (!TryExportFile(exportPath, item, extension, out var exportFullPath))
return false;
File.WriteAllBytes(exportFullPath, m_Font.m_FontData);
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
return false;
}
private static bool ExportMesh(AssetItem item, string exportPath)
{
var m_Mesh = (Mesh)item.Asset;
@ -332,6 +258,87 @@ namespace AssetStudioCLI
return true;
}
public static bool ExportAnimator(AssetItem item, string exportPath, List<AssetItem> animationList = null)
{
var exportFullPath = Path.Combine(exportPath, "FBX_Animator", item.Text, item.Text + ".fbx");
if (File.Exists(exportFullPath))
{
exportFullPath = Path.Combine(exportPath, item.Text + item.UniqueID, item.Text + ".fbx");
}
var m_Animator = (Animator)item.Asset;
var convert = animationList != null
? new ModelConverter(m_Animator, CLIOptions.o_imageFormat.Value, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
: new ModelConverter(m_Animator, CLIOptions.o_imageFormat.Value);
ExportFbx(convert, exportFullPath);
return true;
}
private static void ExportFbx(IImported convert, string exportPath)
{
var fbxSettings = new Fbx.Settings
{
BoneSize = CLIOptions.o_fbxBoneSize.Value,
ScaleFactor = CLIOptions.o_fbxScaleFactor.Value,
ExportAllUvsAsDiffuseMaps = CLIOptions.f_fbxUvsAsDiffuseMaps.Value,
ExportAnimations = CLIOptions.o_fbxAnimMode.Value != AnimationExportMode.Skip,
};
ModelExporter.ExportFbx(exportPath, convert, fbxSettings);
}
public static bool ExportRawFile(AssetItem item, string exportPath)
{
if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath, mode: "ExportRaw"))
return false;
switch (item.Asset)
{
case Texture2D m_Texture2D:
if (!string.IsNullOrEmpty(m_Texture2D.m_StreamData?.path))
{
m_Texture2D.image_data.WriteData(exportFullPath.Replace(".dat", "_data.dat"));
}
break;
case AudioClip m_AudioClip:
if (!string.IsNullOrEmpty(m_AudioClip.m_Source))
{
m_AudioClip.m_AudioData.WriteData(exportFullPath.Replace(".dat", "_data.dat"));
}
break;
case VideoClip m_VideoClip:
if (!string.IsNullOrEmpty(m_VideoClip.m_ExternalResources.m_Source))
{
m_VideoClip.m_VideoData.WriteData(exportFullPath.Replace(".dat", "_data.dat"));
}
break;
}
File.WriteAllBytes(exportFullPath, item.Asset.GetRawData());
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
public static bool ExportDumpFile(AssetItem item, string exportPath)
{
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath, mode: "Dump"))
return false;
var str = item.Asset.Dump();
if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)
{
var m_Type = m_MonoBehaviour.ConvertToTypeTree(Studio.assemblyLoader);
str = m_MonoBehaviour.Dump(m_Type);
}
if (string.IsNullOrEmpty(str))
{
str = item.Asset.DumpObject();
}
if (str != null)
{
File.WriteAllText(exportFullPath, str);
Logger.Debug($"{item.TypeString} \"{item.Text}\" saved to \"{exportFullPath}\"");
return true;
}
return false;
}
public static bool ExportConvertFile(AssetItem item, string exportPath)
{
switch (item.Type)
@ -360,6 +367,15 @@ namespace AssetStudioCLI
}
}
public static void ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
{
var convert = animationList != null
? new ModelConverter(gameObject, CLIOptions.o_imageFormat.Value, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
: new ModelConverter(gameObject, CLIOptions.o_imageFormat.Value);
exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx";
ExportFbx(convert, exportPath);
}
public static string FixFileName(string str)
{
return str.Length >= 260

View File

@ -27,6 +27,7 @@ namespace AssetStudioCLI.Options
Info,
Live2D,
SplitObjects,
Animator,
}
internal enum AssetGroupOption
@ -68,6 +69,13 @@ namespace AssetStudioCLI.Options
NameAndContainer,
}
internal enum AnimationExportMode
{
Auto,
Skip,
All,
}
internal static class CLIOptions
{
public static bool isParsed;
@ -102,6 +110,7 @@ namespace AssetStudioCLI.Options
//fbx
public static Option<float> o_fbxScaleFactor;
public static Option<int> o_fbxBoneSize;
public static Option<AnimationExportMode> o_fbxAnimMode;
public static Option<bool> f_fbxUvsAsDiffuseMaps;
//filter
public static Option<List<string>> o_filterByName;
@ -186,14 +195,15 @@ namespace AssetStudioCLI.Options
optionDefaultValue: WorkMode.Export,
optionName: "-m, --mode <value>",
optionDescription: "Specify working mode\n" +
"<Value: extract | export(default) | exportRaw | dump | info | live2d | splitObjects>\n" +
"Extract - Extracts(Decompresses) asset bundles\n" +
"Export - Exports converted assets\n" +
"ExportRaw - Exports raw data\n" +
"Dump - Makes asset dumps\n" +
"Info - Loads file(s), shows the number of available for export assets and exits\n" +
"Live2D - Exports Live2D Cubism models\n" +
"SplitObjects - Exports split objects (fbx)\n",
"<Value: extract | export(default) | exportRaw | dump | info | live2d |\nsplitObjects | animator>\n" +
"Extract - Extract(Decompress) asset bundles\n" +
"Export - Convert and export assets\n" +
"ExportRaw - Export raw assets\n" +
"Dump - Generate json dumps of loaded asset\n" +
"Info - Load file(s) and show the number of available for export assets\n" +
"Live2D - Export Live2D Cubism models\n" +
"SplitObjects - Export all model objects (split) (fbx)\n" +
"Animator - Export Animator assets (fbx)\n",
optionExample: "Example: \"-m info\"\n",
optionHelpGroup: HelpGroups.General
);
@ -368,6 +378,18 @@ namespace AssetStudioCLI.Options
optionExample: "Example: \"--fbx-bone-size 10\"\n",
optionHelpGroup: HelpGroups.FBX
);
o_fbxAnimMode = new GroupedOption<AnimationExportMode>
(
optionDefaultValue: AnimationExportMode.Auto,
optionName: "--fbx-animation",
optionDescription: "Specify the FBX animation export mode\n" +
"<Value: auto(default) | skip | all>\n" +
"Auto - Search for model-related animations and export model with them\n" +
"Skip - Don't export animations\n" +
"All - Try to bind all loaded animations to each loaded model\n",
optionExample: "--fbx-animation skip\n",
optionHelpGroup: HelpGroups.FBX
);
f_fbxUvsAsDiffuseMaps = new GroupedOption<bool>
(
optionDefaultValue: false,
@ -613,22 +635,23 @@ namespace AssetStudioCLI.Options
o_workMode.Value = WorkMode.Live2D;
o_exportAssetTypes.Value = new List<ClassIDType>
{
ClassIDType.Animation,
ClassIDType.AnimationClip,
ClassIDType.Animator,
ClassIDType.AnimatorController,
ClassIDType.MonoBehaviour,
ClassIDType.Texture2D,
};
break;
case "animator":
case "splitobjects":
o_workMode.Value = WorkMode.SplitObjects;
o_workMode.Value = value.ToLower() == "animator"
? WorkMode.Animator
: WorkMode.SplitObjects;
o_exportAssetTypes.Value = new List<ClassIDType>
{
ClassIDType.Texture2D,
ClassIDType.Material,
ClassIDType.Animator,
ClassIDType.Mesh,
ClassIDType.MeshRenderer,
ClassIDType.MeshFilter,
ClassIDType.SkinnedMeshRenderer,
ClassIDType.Texture2D,
};
break;
default:
@ -719,13 +742,19 @@ namespace AssetStudioCLI.Options
{
case "-t":
case "--asset-type":
if (o_workMode.Value == WorkMode.Live2D || o_workMode.Value == WorkMode.SplitObjects)
if (o_workMode.Value == WorkMode.Live2D || o_workMode.Value == WorkMode.SplitObjects || o_workMode.Value == WorkMode.Animator)
{
i++;
continue;
}
var splittedTypes = ValueSplitter(value);
o_exportAssetTypes.Value = new List<ClassIDType>();
if (splittedTypes.Contains("all", StringComparer.OrdinalIgnoreCase))
{
o_exportAssetTypes.Value = exportableAssetTypes;
i++;
continue;
}
foreach (var type in splittedTypes)
{
switch (type.ToLower())
@ -742,8 +771,14 @@ namespace AssetStudioCLI.Options
case "video":
o_exportAssetTypes.Value.Add(ClassIDType.VideoClip);
break;
case "all":
o_exportAssetTypes.Value = exportableAssetTypes;
case "animator":
if (o_workMode.Value == WorkMode.Export)
{
Console.WriteLine($"{"Not supported in current mode".Color(brightYellow)}. To export Animator assets use \"Animator mode\".\n");
ShowOptionDescription(o_workMode);
return;
}
o_exportAssetTypes.Value.Add(ClassIDType.Animator);
break;
default:
var isKnownType = knownAssetTypesDict.TryGetValue(type.ToLower(), out var assetType);
@ -1007,6 +1042,24 @@ namespace AssetStudioCLI.Options
}
break;
}
case "--fbx-animation":
switch (value.ToLower())
{
case "auto":
o_fbxAnimMode.Value = AnimationExportMode.Auto;
break;
case "skip":
o_fbxAnimMode.Value = AnimationExportMode.Skip;
break;
case "all":
o_fbxAnimMode.Value = AnimationExportMode.All;
break;
default:
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option.Color(brightYellow)}] option. Unsupported animation export mode: [{value.Color(brightRed)}].\n");
ShowOptionDescription(o_fbxAnimMode);
return;
}
break;
case "--blockinfo-comp":
switch (value.ToLower())
{
@ -1357,15 +1410,17 @@ namespace AssetStudioCLI.Options
break;
case WorkMode.Live2D:
case WorkMode.SplitObjects:
case WorkMode.Animator:
sb.AppendLine($"# Log Level: {o_logLevel}");
sb.AppendLine($"# Log Output: {o_logOutput}");
sb.AppendLine($"# Export Asset List: {o_exportAssetList}");
if (o_workMode.Value == WorkMode.SplitObjects)
if (o_workMode.Value == WorkMode.SplitObjects || o_workMode.Value == WorkMode.Animator)
{
sb.AppendLine($"# Export Image Format: {o_imageFormat}");
sb.AppendLine($"# Filter by Name(s): \"{string.Join("\", \"", o_filterByName.Value)}\"");
sb.AppendLine($"# FBX Scale Factor: {o_fbxScaleFactor}");
sb.AppendLine($"# FBX Bone Size: {o_fbxBoneSize}");
sb.AppendLine($"# FBX Animation Mode: {o_fbxAnimMode}");
sb.AppendLine($"# FBX UVs as Diffuse Maps: {f_fbxUvsAsDiffuseMaps}");
}
else

View File

@ -58,6 +58,9 @@ namespace AssetStudioCLI
case WorkMode.SplitObjects:
Studio.ExportSplitObjects();
break;
case WorkMode.Animator:
Studio.ExportAnimator();
break;
default:
Studio.ExportAssets();
break;

View File

@ -526,6 +526,7 @@ namespace AssetStudioCLI
{
case WorkMode.Live2D:
case WorkMode.SplitObjects:
case WorkMode.Animator:
break;
default:
FilterAssets();
@ -917,6 +918,62 @@ namespace AssetStudioCLI
}
}
public static void ExportAnimator()
{
var animationList = CLIOptions.o_fbxAnimMode.Value == AnimationExportMode.Auto
? null
: new List<AssetItem>();
var exportAllAnimations = CLIOptions.o_fbxAnimMode.Value == AnimationExportMode.All;
Logger.Info("Searching for Animator assets...");
var animatorList = new List<AssetItem>();
foreach (var asset in parsedAssetsList)
{
switch (asset.Type)
{
case ClassIDType.Animator:
animatorList.Add(asset);
break;
case ClassIDType.AnimationClip when exportAllAnimations:
animationList?.Add(asset);
break;
}
}
parsedAssetsList = animatorList;
Logger.Info($"Found {parsedAssetsList.Count} exportable Animator asset(s).");
if (parsedAssetsList.Count > 0 && CLIOptions.filterBy != FilterBy.None)
{
FilterAssets();
}
var savePath = CLIOptions.o_outputFolder.Value;
var toExportCount = parsedAssetsList.Count;
var exportedCount = 0;
Progress.Reset();
foreach (var asset in parsedAssetsList)
{
var isExported = false;
Logger.Info($"[{exportedCount + 1}/{toExportCount}] Exporting \"{asset.Text}\"...");
try
{
Logger.Debug($"Animator Export: {asset.Type} : {asset.Container} : {asset.Text}");
isExported = Exporter.ExportAnimator(asset, savePath, animationList);
}
catch (Exception ex)
{
Logger.Error($"{asset.SourceFile.originalPath ?? asset.SourceFile.fullName}: [{$"{asset.Type}: {asset.Text}".Color(Ansi.BrightRed)}] : Export error\n{ex}");
}
if (isExported)
{
exportedCount++;
}
}
var status = exportedCount > 0
? $"Finished exporting [{exportedCount}/{toExportCount}] Animator asset(s) to \"{CLIOptions.o_outputFolder.Value.Color(Ansi.BrightCyan)}\""
: "Nothing exported";
Logger.Default.Log(LoggerEvent.Info, status, ignoreLevel: true);
}
private static bool TryGetCubismMoc(MonoBehaviour m_MonoBehaviour, out MonoBehaviour mocMono)
{
mocMono = null;