Skip to content

Instantly share code, notes, and snippets.

@8chan-co
Last active July 22, 2024 09:10
Show Gist options
  • Save 8chan-co/ae6798c4f4764a97d0d9872741561cb1 to your computer and use it in GitHub Desktop.
Save 8chan-co/ae6798c4f4764a97d0d9872741561cb1 to your computer and use it in GitHub Desktop.
using Autodesk.Fbx;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
internal sealed class ClearVertexColors : EditorWindow
{
private sealed class AssetDeletionProcessor : AssetModificationProcessor
{
internal static event System.Action<string> OnAssetDeleted;
private static AssetDeleteResult OnWillDeleteAsset(string path, RemoveAssetOptions _)
{
if (OnAssetDeleted is not null) OnAssetDeleted(path);
return AssetDeleteResult.DidNotDelete;
}
}
private string _assetPath;
private static string s_title;
[MenuItem("Tools/Clear Vertex Colors")]
private static void GetWindow()
{
s_title = ObjectNames.NicifyVariableName(nameof(ClearVertexColors));
var window = GetWindow<ClearVertexColors>(utility: true, s_title);
window.maxSize = new Vector2(300, 100);
window.minSize = window.maxSize;
}
private void CreateGUI()
{
ObjectField field = new("Target FBX")
{
objectType = typeof(GameObject),
allowSceneObjects = false
};
Button butt = new(OverwriteWithoutVertexColors)
{
text = ObjectNames.NicifyVariableName(nameof(ClearAllVertexColors))
};
butt.SetEnabled(false);
field.RegisterValueChangedCallback(changed =>
{
butt.SetEnabled(changed.newValue);
if (changed.newValue == null) return;
_assetPath = AssetDatabase.GetAssetPath(changed.newValue);
});
AssetDeletionProcessor.OnAssetDeleted +=
path => butt.SetEnabled(path.Equals(_assetPath) ^ true);
rootVisualElement.Add(field);
rootVisualElement.Add(butt);
}
private void OverwriteWithoutVertexColors()
{
using var manager = FbxManager.Create();
using var importer = FbxImporter.Create(manager, string.Empty);
if (importer.Initialize(_assetPath) is false)
{
DisplayIOError(importer, clearProgressBar: false);
return;
}
using var scene = FbxScene.Create(manager, string.Empty);
importer.SetProgressCallback(FbxExportProgressCallback);
if (importer.Import(scene) is false)
{
DisplayIOError(importer, clearProgressBar: true);
return;
}
EditorUtility.ClearProgressBar();
ClearAllVertexColors(scene.GetRootNode());
using var exporter = FbxExporter.Create(manager, string.Empty);
if (exporter.Initialize(_assetPath) is false)
{
DisplayIOError(exporter, clearProgressBar: false);
return;
}
exporter.SetProgressCallback(FbxExportProgressCallback);
if (exporter.Export(scene) is false)
{
DisplayIOError(exporter, clearProgressBar: true);
return;
}
EditorUtility.ClearProgressBar();
AssetDatabase.ImportAsset(_assetPath, ImportAssetOptions.ForceUpdate);
}
private static void ClearAllVertexColors(FbxNode root)
{
for (var i = 0; i < root.GetChildCount(); ++i)
{
var child = root.GetChild(i);
var mesh = child.GetMesh();
if (mesh is null) continue;
for (var j = 0; j < mesh.GetLayerCount(); ++j)
{
var layer = mesh.GetLayer(j);
if (layer.GetVertexColors() is null) continue;
layer.SetVertexColors(null);
}
}
}
private static void DisplayIOError(FbxIOBase io, bool clearProgressBar)
{
if (clearProgressBar) EditorUtility.ClearProgressBar();
var error = io.GetStatus().GetErrorString();
EditorUtility.DisplayDialog(s_title, error, "Ok");
}
private static bool FbxExportProgressCallback(float percentage, string status)
{
percentage = 0.5F * (1F + (percentage / 100F));
EditorUtility.DisplayProgressBar(s_title, status, percentage);
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment