Skip to content

Instantly share code, notes, and snippets.

@wotakuro
Created June 1, 2021 23:07
Show Gist options
  • Save wotakuro/0e80666891bc1e556915ceb0c75472cc to your computer and use it in GitHub Desktop.
Save wotakuro/0e80666891bc1e556915ceb0c75472cc to your computer and use it in GitHub Desktop.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace UTJ
{
// window
public class MaterialColorCurveConvert : EditorWindow
{
private AnimationClip clip;
[MenuItem("Tools/AnimationMaterialCurve")]
public static void Create()
{
EditorWindow.GetWindow<MaterialColorCurveConvert>();
}
private void OnGUI()
{
this.clip = EditorGUILayout.ObjectField(clip, typeof(AnimationClip), false) as AnimationClip;
if (GUILayout.Button("Exec"))
{
var converter = new AnimationClipConverter();
converter.ConvertToVectorOnly(this.clip);
}
}
}
// コンバート本体
class AnimationClipConverter
{
[System.Flags]
public enum PropertyType : int
{
None = 0x00,
Vector = 0x01,
Color = 0x02,
Both = 0x03
}
static readonly string HeaderMaterial = "material.";
static readonly string[] FooterRGBA = new string[] { ".r", ".g", ".b", ".a" };
static readonly string[] FooterXYZW = new string[] { ".x", ".y", ".z", ".w" };
private Dictionary<string, PropertyType> materialProperty = new Dictionary<string, PropertyType>();
private List<EditorCurveBinding> editorCurveBindings = new List<EditorCurveBinding>();
private List<AnimationCurve> curves = new List<AnimationCurve>();
private HashSet<string> excludeShaderProp = new HashSet<string>(); // このShaderProperty名だけは除去したいという時用
// VectorのみのAnimationClipに変換します
public void ConvertToVectorOnly(AnimationClip clip)
{
this.materialProperty.Clear();
this.editorCurveBindings.Clear();
this.curves.Clear();
var bindings = AnimationUtility.GetCurveBindings(clip);
this.ConstructMaterialProperty(bindings);
// RGBAのものをXYZWに変換して、その部分だけにします
this.ConstructVectorOnlyCurve(clip, bindings);
// そして最後に書き込み
OverwriteToAnimationClip(clip);
}
// AnimationClipを現在のEditorCurveBindings/curvesで置き換えます
private void OverwriteToAnimationClip(AnimationClip clip)
{
clip.ClearCurves();
for (int i = 0; i < this.editorCurveBindings.Count; ++i)
{
AnimationUtility.SetEditorCurve(clip, this.editorCurveBindings[i], this.curves[i]);
}
}
// Vectorのみのカーブに変換します
private void ConstructVectorOnlyCurve(AnimationClip clip, EditorCurveBinding[] bindings)
{
foreach (var binding in bindings)
{
var curve = AnimationUtility.GetEditorCurve(clip, binding);
// マテリアルじゃないならそのまま追加
if (!IsMaterialPropertyCurve(binding))
{
this.editorCurveBindings.Add(binding);
this.curves.Add(curve);
continue;
}
// Shader名
var shaderPropName = GetShaderPropertyName(binding);
PropertyType propertyType = PropertyType.None;
// ないなら or 除去リストならそのまま追加
if (!this.materialProperty.TryGetValue(shaderPropName, out propertyType) &&
excludeShaderProp.Contains(shaderPropName))
{
this.editorCurveBindings.Add(binding);
this.curves.Add(curve);
continue;
}
// RGBAだったらXYZWに変換します
var newBinding = binding;
if (propertyType == PropertyType.Color)
{
newBinding = ConvertToVector(binding);
}
this.editorCurveBindings.Add(newBinding);
this.curves.Add(curve);
}
}
// RGBA -> XYZWにコンバートします
private EditorCurveBinding ConvertToVector(EditorCurveBinding binding)
{
for (int i = 0; i < FooterRGBA.Length; ++i)
{
if (binding.propertyName.EndsWith(FooterRGBA[i]))
{
var str = binding.propertyName.Substring(0, binding.propertyName.Length - 2);
binding.propertyName = str + FooterXYZW[i];
break;
}
}
return binding;
}
// Shaderのプロパティ名を取得します
private string GetShaderPropertyName(EditorCurveBinding binding)
{
string shaderPropName =
binding.propertyName.Substring(HeaderMaterial.Length, binding.propertyName.Length - HeaderMaterial.Length - 2);
return shaderPropName;
}
// Materialのカーブかどうか返します
private bool IsMaterialPropertyCurve(EditorCurveBinding binding)
{
bool isRenderer = binding.type.IsSubclassOf(typeof(Renderer));
if (!isRenderer) { return false; }
var propertyName = binding.propertyName;
if (!propertyName.StartsWith(HeaderMaterial))
{
return false;
}
return true;
}
// Materialのプロパティ情報を構築します
private void ConstructMaterialProperty(EditorCurveBinding[] bindings)
{
foreach (var binding in bindings)
{
if (!IsMaterialPropertyCurve(binding))
{
continue;
}
var propertyName = binding.propertyName;
PropertyType propertyType = PropertyType.None;
string shaderPropName = GetShaderPropertyName(binding);
if (!this.materialProperty.TryGetValue(shaderPropName, out propertyType))
{
propertyType = PropertyType.None;
}
if (IsPorpertyXYZW(propertyName))
{
propertyType |= PropertyType.Vector;
}
else if (IsPorpertyRGBA(propertyName))
{
propertyType |= PropertyType.Color;
}
if (propertyType == PropertyType.None)
{
continue;
}
this.materialProperty[shaderPropName] = propertyType;
}
}
// PropertyがRGBAであるかどうか?
private bool IsPorpertyRGBA(string str)
{
for (int i = 0; i < FooterRGBA.Length; ++i)
{
if (str.EndsWith(FooterRGBA[i]))
{
return true;
}
}
return false;
}
// PropertyがXYZWであるかどうか?
private bool IsPorpertyXYZW(string str)
{
for (int i = 0; i < FooterXYZW.Length; ++i)
{
if (str.EndsWith(FooterXYZW[i]))
{
return true;
}
}
return false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment