[GUI] Some fixes for animation export

- Disabled animation converting if animation export is disabled in the options
- Fixed a bug with ignoring animation selection order when exporting models with selected animationClips via the “Model” tab
This commit is contained in:
VaDiM
2025-08-10 02:23:22 +03:00
parent 054906a426
commit be11fdf14f
6 changed files with 82 additions and 79 deletions

View File

@ -150,10 +150,7 @@ namespace AssetStudioGUI
assetsManager.Options.BundleOptions.DecompressToDisk = Properties.Settings.Default.decompressToDisk;
FMODinit();
listSearchFilterMode.SelectedIndex = 0;
if (string.IsNullOrEmpty(Properties.Settings.Default.fbxSettings))
{
FBXinitOptions();
}
FbxInitOptions(Properties.Settings.Default.fbxSettings);
logger = new GUILogger(StatusStripUpdate);
Logger.Default = logger;
@ -1700,26 +1697,18 @@ namespace AssetStudioGUI
private void exportAnimatorWithAnimationClipMenuItem_Click(object sender, EventArgs e)
{
AssetItem animator = null;
var selectedAssets = GetSelectedAssets();
foreach (var assetPreloadData in selectedAssets)
{
if (assetPreloadData.Type == ClassIDType.Animator)
{
animator = assetPreloadData;
}
}
var animator = selectedAssets.FirstOrDefault(x => x.Type == ClassIDType.Animator);
if (animator == null)
return;
if (animator != null)
var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)
{
var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)
{
saveDirectoryBackup = saveFolderDialog.Folder;
var exportPath = Path.Combine(saveFolderDialog.Folder, "Animator") + Path.DirectorySeparatorChar;
ExportAnimatorWithAnimationClip(animator, selectedAnimationAssetsList, exportPath);
}
saveDirectoryBackup = saveFolderDialog.Folder;
var exportPath = Path.Combine(saveFolderDialog.Folder, "Animator") + Path.DirectorySeparatorChar;
ExportAnimatorWithAnimationClip(animator, selectedAnimationAssetsList, exportPath);
}
}
@ -1744,13 +1733,9 @@ namespace AssetStudioGUI
saveDirectoryBackup = saveFolderDialog.Folder;
var exportPath = Path.Combine(saveFolderDialog.Folder, "GameObject") + Path.DirectorySeparatorChar;
List<AssetItem> animationList = null;
if (animation)
if(animation && selectedAnimationAssetsList.Count > 0)
{
animationList = GetSelectedAssets().Where(x => x.Type == ClassIDType.AnimationClip).ToList();
if (animationList.Count == 0)
{
animationList = null;
}
animationList = selectedAnimationAssetsList;
}
ExportObjectsWithAnimationClip(exportPath, sceneTreeView.Nodes, animationList);
}
@ -1789,13 +1774,9 @@ namespace AssetStudioGUI
saveDirectoryBackup = Path.GetDirectoryName(saveFileDialog.FileName);
var exportPath = saveFileDialog.FileName;
List<AssetItem> animationList = null;
if (animation)
if (animation && selectedAnimationAssetsList.Count > 0)
{
animationList = GetSelectedAssets().Where(x => x.Type == ClassIDType.AnimationClip).ToList();
if (animationList.Count == 0)
{
animationList = null;
}
animationList = selectedAnimationAssetsList;
}
ExportObjectsMergeWithAnimationClip(exportPath, gameObjects, animationList);
}
@ -2672,10 +2653,18 @@ namespace AssetStudioGUI
Properties.Settings.Default.Save();
}
private void FBXinitOptions()
private static void FbxInitOptions(string base64String)
{
Properties.Settings.Default.fbxSettings = new Fbx.Settings().ToBase64();
Properties.Settings.Default.Save();
if (string.IsNullOrEmpty(base64String))
{
Studio.FbxSettings = new Fbx.Settings();
Properties.Settings.Default.fbxSettings = Studio.FbxSettings.ToBase64();
Properties.Settings.Default.Save();
}
else
{
Studio.FbxSettings = Fbx.Settings.FromBase64(base64String);
}
}
#region FMOD

View File

@ -1,5 +1,6 @@
using AssetStudio;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
@ -7,7 +8,7 @@ namespace AssetStudioGUI
{
public partial class ExportOptions : Form
{
private static Fbx.Settings fbxSettings;
private static Dictionary<int, int> uvBindings;
public ExportOptions()
{
@ -34,8 +35,7 @@ namespace AssetStudioGUI
((RadioButton)l2dMotionExportMethodPanel.Controls.Cast<Control>().First(x => x.AccessibleName == defaultMotionMode)).Checked = true;
l2dForceBezierCheckBox.Checked = Properties.Settings.Default.l2dForceBezier;
fbxSettings = Fbx.Settings.FromBase64(Properties.Settings.Default.fbxSettings);
SetFromFbxSettings();
SetFromFbxSettings(Studio.FbxSettings);
}
private void OKbutton_Click(object sender, EventArgs e)
@ -58,26 +58,27 @@ namespace AssetStudioGUI
Properties.Settings.Default.l2dMotionMode = (CubismLive2DExtractor.Live2DMotionMode)Enum.Parse(typeof(CubismLive2DExtractor.Live2DMotionMode), checkedMotionMode.AccessibleName);
Properties.Settings.Default.l2dForceBezier = l2dForceBezierCheckBox.Checked;
fbxSettings.EulerFilter = eulerFilter.Checked;
fbxSettings.FilterPrecision = (float)filterPrecision.Value;
fbxSettings.ExportAllNodes = exportAllNodes.Checked;
fbxSettings.ExportSkins = exportSkins.Checked;
fbxSettings.ExportAnimations = exportAnimations.Checked;
fbxSettings.ExportBlendShape = exportBlendShape.Checked;
fbxSettings.CastToBone = castToBone.Checked;
fbxSettings.ExportAllUvsAsDiffuseMaps = exportAllUvsAsDiffuseMaps.Checked;
fbxSettings.BoneSize = (int)boneSize.Value;
fbxSettings.ScaleFactor = (float)scaleFactor.Value;
fbxSettings.FbxVersionIndex = fbxVersion.SelectedIndex;
fbxSettings.FbxFormat = fbxFormat.SelectedIndex;
Studio.FbxSettings.EulerFilter = eulerFilter.Checked;
Studio.FbxSettings.FilterPrecision = (float)filterPrecision.Value;
Studio.FbxSettings.ExportAllNodes = exportAllNodes.Checked;
Studio.FbxSettings.ExportSkins = exportSkins.Checked;
Studio.FbxSettings.ExportAnimations = exportAnimations.Checked;
Studio.FbxSettings.ExportBlendShape = exportBlendShape.Checked;
Studio.FbxSettings.CastToBone = castToBone.Checked;
Studio.FbxSettings.ExportAllUvsAsDiffuseMaps = exportAllUvsAsDiffuseMaps.Checked;
Studio.FbxSettings.BoneSize = (int)boneSize.Value;
Studio.FbxSettings.ScaleFactor = (float)scaleFactor.Value;
Studio.FbxSettings.FbxVersionIndex = fbxVersion.SelectedIndex;
Studio.FbxSettings.FbxFormat = fbxFormat.SelectedIndex;
for (var i = 0; i < uvIndicesCheckedListBox.Items.Count; i++)
{
var isChecked = uvIndicesCheckedListBox.GetItemChecked(i);
var type = fbxSettings.UvBindings[i];
var type = uvBindings[i];
if ((isChecked && type < 0) || (!isChecked && type > 0))
fbxSettings.UvBindings[i] *= -1;
uvBindings[i] *= -1;
}
Properties.Settings.Default.fbxSettings = fbxSettings.ToBase64();
Studio.FbxSettings.UvBindings = uvBindings;
Properties.Settings.Default.fbxSettings = Studio.FbxSettings.ToBase64();
Properties.Settings.Default.Save();
DialogResult = DialogResult.OK;
@ -100,7 +101,7 @@ namespace AssetStudioGUI
if (exportAllUvsAsDiffuseMaps.Checked)
return;
if (fbxSettings.UvBindings.TryGetValue(uvIndicesCheckedListBox.SelectedIndex, out var uvType))
if (uvBindings.TryGetValue(uvIndicesCheckedListBox.SelectedIndex, out var uvType))
{
uvTypesListBox.SelectedIndex = (int)MathF.Abs(uvType) - 1;
}
@ -109,7 +110,7 @@ namespace AssetStudioGUI
private void uvTypesListBox_SelectedIndexChanged(object sender, EventArgs e)
{
var selectedUv = uvIndicesCheckedListBox.SelectedIndex;
fbxSettings.UvBindings[selectedUv] = uvTypesListBox.SelectedIndex + 1;
uvBindings[selectedUv] = uvTypesListBox.SelectedIndex + 1;
}
private void exportAllUvsAsDiffuseMaps_CheckedChanged(object sender, EventArgs e)
@ -118,7 +119,7 @@ namespace AssetStudioGUI
uvIndicesCheckedListBox.Enabled = !exportAllUvsAsDiffuseMaps.Checked;
}
private void SetFromFbxSettings()
private void SetFromFbxSettings(Fbx.Settings fbxSettings)
{
eulerFilter.Checked = fbxSettings.EulerFilter;
filterPrecision.Value = (decimal)fbxSettings.FilterPrecision;
@ -132,9 +133,10 @@ namespace AssetStudioGUI
scaleFactor.Value = (decimal)fbxSettings.ScaleFactor;
fbxVersion.SelectedIndex = fbxSettings.FbxVersionIndex;
fbxFormat.SelectedIndex = fbxSettings.FbxFormat;
uvBindings = new Dictionary<int, int>(fbxSettings.UvBindings);
for (var i = 0; i < uvIndicesCheckedListBox.Items.Count; i++)
{
var isChecked = fbxSettings.UvBindings[i] > 0;
var isChecked = uvBindings[i] > 0;
uvIndicesCheckedListBox.SetItemChecked(i, isChecked);
}
uvTypesListBox.Enabled = !exportAllUvsAsDiffuseMaps.Checked;
@ -143,8 +145,7 @@ namespace AssetStudioGUI
private void resetButton_Click(object sender, EventArgs e)
{
fbxSettings.Init();
SetFromFbxSettings();
SetFromFbxSettings(new Fbx.Settings());
uvIndicesCheckedListBox_SelectedIndexChanged(sender, e);
}
}

View File

@ -222,9 +222,11 @@ namespace AssetStudioGUI
{
exportFullPath = Path.Combine(exportPath, item.Text + item.UniqueID, item.Text + ".fbx");
}
if (!Studio.FbxSettings.ExportAnimations)
animationList = new List<AssetItem>();
var m_Animator = (Animator)item.Asset;
var convert = animationList != null
? new ModelConverter(m_Animator, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
? new ModelConverter(m_Animator, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToList())
: new ModelConverter(m_Animator, Properties.Settings.Default.convertType);
ExportFbx(convert, exportFullPath);
return true;
@ -232,8 +234,7 @@ namespace AssetStudioGUI
private static void ExportFbx(IImported convert, string exportPath)
{
var fbxSettings = Fbx.Settings.FromBase64(Properties.Settings.Default.fbxSettings);
ModelExporter.ExportFbx(exportPath, convert, fbxSettings);
ModelExporter.ExportFbx(exportPath, convert, Studio.FbxSettings);
}
public static bool ExportRawFile(AssetItem item, string exportPath)
@ -322,8 +323,10 @@ namespace AssetStudioGUI
public static void ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
{
if (!Studio.FbxSettings.ExportAnimations)
animationList = new List<AssetItem>();
var convert = animationList != null
? new ModelConverter(gameObject, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
? new ModelConverter(gameObject, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToList())
: new ModelConverter(gameObject, Properties.Settings.Default.convertType);
exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx";
ExportFbx(convert, exportPath);
@ -332,8 +335,10 @@ namespace AssetStudioGUI
public static void ExportGameObjectMerge(List<GameObject> gameObject, string exportPath, List<AssetItem> animationList = null)
{
var rootName = Path.GetFileNameWithoutExtension(exportPath);
if (!Studio.FbxSettings.ExportAnimations)
animationList = new List<AssetItem>();
var convert = animationList != null
? new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
? new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToList())
: new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType);
ExportFbx(convert, exportPath);
}

View File

@ -90,6 +90,7 @@ namespace AssetStudioGUI
public static Dictionary<MonoBehaviour, CubismModel> l2dModelDict = new Dictionary<MonoBehaviour, CubismModel>();
private static Dictionary<Object, string> l2dAssetContainers = new Dictionary<Object, string>();
internal static Action<string> StatusStripUpdate = x => { };
internal static Fbx.Settings FbxSettings;
public static int ExtractFolder(string path, string savePath)
{
@ -861,7 +862,6 @@ namespace AssetStudioGUI
{
Progress.Reset();
Logger.Info($"Exporting {animator.Text}");
Logger.Debug($"Selected AnimationClip(s):\n\"{string.Join("\"\n\"", animationList.Select(x => x.Text))}\"");
try
{
ExportAnimator(animator, exportPath, animationList);