Created
June 1, 2021 23:07
-
-
Save wotakuro/0e80666891bc1e556915ceb0c75472cc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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