mirror of
https://github.com/maxartz15/VertexAnimation.git
synced 2024-11-12 15:35:30 +01:00
Model Baker
Model Baker ScriptableObject, bakes models and outputs the data. Can also generate prefab and animation books for quick setup. Updated GUI.
This commit is contained in:
parent
abd6cc9e9e
commit
cab2c4ad12
20
Editor/Scripts/Editor/EditorGUILayoutUtils.cs
Normal file
20
Editor/Scripts/Editor/EditorGUILayoutUtils.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TAO.VertexAnimation.Editor
|
||||
{
|
||||
public static class EditorGUILayoutUtils
|
||||
{
|
||||
public static readonly Color horizontalLineColor = Color.white;
|
||||
|
||||
public static void HorizontalLine(Color color)
|
||||
{
|
||||
Color prev = GUI.color;
|
||||
GUI.color = color;
|
||||
EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
|
||||
GUI.color = prev;
|
||||
}
|
||||
|
||||
public static void HorizontalLine() => HorizontalLine(horizontalLineColor);
|
||||
}
|
||||
}
|
11
Editor/Scripts/Editor/EditorGUILayoutUtils.cs.meta
Normal file
11
Editor/Scripts/Editor/EditorGUILayoutUtils.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a78d6eea6c7f534b8361125e43eacc9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,109 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TAO.VertexAnimation.Editor
|
||||
{
|
||||
[CustomEditor(typeof(VA_ModelBaker))]
|
||||
public class VA_ModelBakerEditor : UnityEditor.Editor
|
||||
{
|
||||
private VA_ModelBaker modelBaker = null;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
modelBaker = target as VA_ModelBaker;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
InputGUI();
|
||||
BakeGUI();
|
||||
OutputGUI();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private void InputGUI()
|
||||
{
|
||||
//public GameObject model;
|
||||
//public AnimationClip[] animationClips;
|
||||
//public int fps = 24;
|
||||
//public int textureWidth = 512;
|
||||
//public bool saveBakedDataToAsset = true;
|
||||
//public bool generateAnimationBook = false;
|
||||
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("model"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("animationClips"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("fps"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("textureWidth"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("saveBakedDataToAsset"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("generateAnimationBook"));
|
||||
}
|
||||
|
||||
private void BakeGUI()
|
||||
{
|
||||
if (GUILayout.Button("Bake"))
|
||||
{
|
||||
ClearBakedData();
|
||||
|
||||
modelBaker.Bake();
|
||||
|
||||
if (modelBaker.saveBakedDataToAsset)
|
||||
{
|
||||
SaveBakedData();
|
||||
}
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("SaveBakedData", EditorStyles.miniButtonLeft))
|
||||
{
|
||||
SaveBakedData();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("ClearBakedData", EditorStyles.miniButtonRight))
|
||||
{
|
||||
ClearBakedData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OutputGUI()
|
||||
{
|
||||
using (new EditorGUI.DisabledGroupScope(true))
|
||||
{
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("bakedData"));
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveBakedData()
|
||||
{
|
||||
AssetDatabase.AddObjectToAsset(modelBaker.BakedData.mesh, modelBaker);
|
||||
|
||||
foreach (var pm in modelBaker.BakedData.positionMaps)
|
||||
{
|
||||
AssetDatabase.AddObjectToAsset(pm, modelBaker);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
private void ClearBakedData()
|
||||
{
|
||||
var assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(modelBaker));
|
||||
|
||||
foreach (var a in assets)
|
||||
{
|
||||
if (a != modelBaker)
|
||||
{
|
||||
AssetDatabase.RemoveObjectFromAsset(a);
|
||||
}
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
@ -10,10 +10,6 @@ namespace TAO.VertexAnimation.Editor
|
||||
private Vector2 textureGroupScollPos;
|
||||
private Vector2 animationPagesScollPos;
|
||||
|
||||
//private UnityEditor.Editor previewEditor = null;
|
||||
//private int previewIndex = 0;
|
||||
//private int curviewIndex = 0;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
animationBook = target as VA_AnimationBook;
|
||||
@ -25,11 +21,16 @@ namespace TAO.VertexAnimation.Editor
|
||||
|
||||
// Texture Groups.
|
||||
GeneralGUI();
|
||||
EditorGUILayoutUtils.HorizontalLine(color: Color.gray);
|
||||
TextureGroupsGUI();
|
||||
EditorGUILayoutUtils.HorizontalLine(color: Color.gray);
|
||||
SyncListSize();
|
||||
AnimationPagesGUI();
|
||||
EditorGUILayoutUtils.HorizontalLine(color: Color.gray);
|
||||
MaterialGUI();
|
||||
EditorGUILayoutUtils.HorizontalLine(color: Color.gray);
|
||||
AssetBuilderGUI();
|
||||
EditorGUILayoutUtils.HorizontalLine(color: Color.gray);
|
||||
Texture2DGUI();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
216
Editor/Scripts/ModelBaker/Editor/VA_ModelBakerEditor.cs
Normal file
216
Editor/Scripts/ModelBaker/Editor/VA_ModelBakerEditor.cs
Normal file
@ -0,0 +1,216 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace TAO.VertexAnimation.Editor
|
||||
{
|
||||
[CustomEditor(typeof(VA_ModelBaker))]
|
||||
public class VA_ModelBakerEditor : UnityEditor.Editor
|
||||
{
|
||||
private VA_ModelBaker modelBaker = null;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
modelBaker = target as VA_ModelBaker;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
InputGUI();
|
||||
EditorGUILayoutUtils.HorizontalLine(color: Color.gray);
|
||||
BakeGUI();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
EditorGUILayoutUtils.HorizontalLine(color: Color.gray);
|
||||
OutputGUI();
|
||||
}
|
||||
|
||||
private void InputGUI()
|
||||
{
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("model"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("animationClips"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("fps"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("textureWidth"));
|
||||
}
|
||||
|
||||
private void BakeGUI()
|
||||
{
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("saveBakedDataToAsset"));
|
||||
|
||||
int il = EditorGUI.indentLevel;
|
||||
if (modelBaker.saveBakedDataToAsset)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("generateAnimationBook"));
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("generatePrefab"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("materialShader"), new GUIContent(""));
|
||||
}
|
||||
}
|
||||
EditorGUI.indentLevel = il;
|
||||
|
||||
if (GUILayout.Button("Bake", GUILayout.Height(32)))
|
||||
{
|
||||
ClearBakedData();
|
||||
|
||||
modelBaker.Bake();
|
||||
|
||||
if (modelBaker.saveBakedDataToAsset)
|
||||
{
|
||||
SaveBakedData();
|
||||
}
|
||||
}
|
||||
|
||||
if (modelBaker.BakedData.mesh != null)
|
||||
{
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Save", EditorStyles.miniButtonLeft))
|
||||
{
|
||||
SaveBakedData();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Clear", EditorStyles.miniButtonRight))
|
||||
{
|
||||
ClearBakedData();
|
||||
}
|
||||
}
|
||||
|
||||
if (modelBaker.prefab && GUILayout.Button("Remove Prefab"))
|
||||
{
|
||||
DeletePrefab();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OutputGUI()
|
||||
{
|
||||
using (new EditorGUI.DisabledGroupScope(true))
|
||||
{
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("bakedData"));
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveBakedData()
|
||||
{
|
||||
ClearBakedData();
|
||||
|
||||
AssetDatabase.AddObjectToAsset(modelBaker.BakedData.mesh, modelBaker);
|
||||
|
||||
foreach (var pm in modelBaker.BakedData.positionMaps)
|
||||
{
|
||||
AssetDatabase.AddObjectToAsset(pm, modelBaker);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
if (modelBaker.generatePrefab)
|
||||
{
|
||||
GeneratePrefab();
|
||||
}
|
||||
|
||||
if(modelBaker.generateAnimationBook)
|
||||
{
|
||||
GenerateBook();
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
private void ClearBakedData()
|
||||
{
|
||||
var assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(modelBaker));
|
||||
|
||||
foreach (var a in assets)
|
||||
{
|
||||
if (a != modelBaker)
|
||||
{
|
||||
AssetDatabase.RemoveObjectFromAsset(a);
|
||||
}
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
private void DeletePrefab()
|
||||
{
|
||||
string path = AssetDatabase.GetAssetPath(modelBaker.prefab);
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
private void GeneratePrefab()
|
||||
{
|
||||
string path = AssetDatabase.GetAssetPath(modelBaker);
|
||||
int start = path.LastIndexOf('/');
|
||||
path = path.Remove(start, path.Length - start);
|
||||
path += "/" + modelBaker.name + ".prefab";
|
||||
|
||||
// Generate Material
|
||||
modelBaker.material = new Material(modelBaker.materialShader);
|
||||
modelBaker.material.name = modelBaker.name;
|
||||
AssetDatabase.AddObjectToAsset(modelBaker.material, modelBaker);
|
||||
|
||||
// Generate Object.
|
||||
if (!modelBaker.prefab)
|
||||
{
|
||||
GameObject go = new GameObject(modelBaker.model.name, typeof(MeshFilter), typeof(MeshRenderer));
|
||||
modelBaker.prefab = PrefabUtility.SaveAsPrefabAssetAndConnect(go, path, InteractionMode.AutomatedAction);
|
||||
DestroyImmediate(go);
|
||||
}
|
||||
|
||||
GameObject inst = PrefabUtility.InstantiatePrefab(modelBaker.prefab) as GameObject;
|
||||
|
||||
inst.GetComponent<MeshFilter>().sharedMesh = modelBaker.BakedData.mesh;
|
||||
inst.GetComponent<MeshRenderer>().sharedMaterial = modelBaker.material;
|
||||
|
||||
// Save.
|
||||
PrefabUtility.ApplyPrefabInstance(inst, InteractionMode.UserAction);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
DestroyImmediate(inst);
|
||||
}
|
||||
|
||||
private void GenerateBook()
|
||||
{
|
||||
if (!modelBaker.book)
|
||||
{
|
||||
modelBaker.book = CreateInstance<VA_AnimationBook>();
|
||||
}
|
||||
|
||||
modelBaker.book.name = modelBaker.model.name;
|
||||
modelBaker.book.editorData = new VA_AnimationBook.EditorData();
|
||||
|
||||
modelBaker.book.editorData.materials = new Material[1] { modelBaker.material };
|
||||
|
||||
foreach (Texture2D tex in modelBaker.BakedData.positionMaps)
|
||||
{
|
||||
modelBaker.book.editorData.animationPages.Add(new VA_AnimationBook.EditorAnimationPage
|
||||
{
|
||||
name = "",
|
||||
frames = 0,
|
||||
textures = new List<VA_AnimationBook.EditorTextureEntry>()
|
||||
{
|
||||
new VA_AnimationBook.EditorTextureEntry
|
||||
{
|
||||
texture2D = tex
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
VA_AssetBuilder.AutoFill(ref modelBaker.book);
|
||||
|
||||
AssetDatabase.AddObjectToAsset(modelBaker.book, modelBaker);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
}
|
@ -293,6 +293,13 @@ namespace TAO.VertexAnimation.Editor
|
||||
ap.frames = frames;
|
||||
}
|
||||
}
|
||||
else if (p.StartsWith("MF-"))
|
||||
{
|
||||
if (int.TryParse(p.Remove(0, 3), out int maxFrames))
|
||||
{
|
||||
book.editorData.maxFrames = maxFrames;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
book.editorData.animationPages[i] = ap;
|
||||
|
@ -1,16 +1,4 @@
|
||||
// References:
|
||||
// https://forum.unity.com/threads/help-combining-and-manipulating-skinned-mesh-renderers-imported-from-blender.505078/
|
||||
// http://wiki.unity3d.com/index.php/CombineSkinnedMeshes
|
||||
// http://wiki.unity3d.com/index.php/SkinnedMeshCombiner
|
||||
|
||||
// TODO:
|
||||
// ---Bake ALL the MeshRenderers/SkinnedMeshRenderers and merge them together.---
|
||||
// ---Bake multiple animations.---
|
||||
// ---Get the longest animation to calculate the texture height, so all the textures have the same height for the 3D texture.---
|
||||
// Add options and previews for texture size, animation phasing/fps.
|
||||
// Either merge with the animation books or generate them from this and maybe store them as child (and then don't destroy them on re-bake to keep the reference but replace it).
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TAO.VertexAnimation
|
||||
@ -9,10 +7,20 @@ namespace TAO.VertexAnimation
|
||||
{
|
||||
public GameObject model;
|
||||
public AnimationClip[] animationClips;
|
||||
[Range(1, 60)]
|
||||
public int fps = 24;
|
||||
public int textureWidth = 512;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public bool saveBakedDataToAsset = true;
|
||||
public bool generateAnimationBook = false;
|
||||
public bool generateAnimationBook = true;
|
||||
public bool generatePrefab = true;
|
||||
public Shader materialShader = null;
|
||||
|
||||
public GameObject prefab = null;
|
||||
public Material material = null;
|
||||
public VA_AnimationBook book = null;
|
||||
#endif
|
||||
|
||||
[SerializeField]
|
||||
private AnimationBaker.BakedData bakedData;
|
||||
|
Loading…
Reference in New Issue
Block a user