mirror of
https://github.com/maxartz15/VertexAnimation.git
synced 2025-06-13 06:46:17 +02:00
Model Baker Updates
... Added fps to book data. Cleanup. Preparing LOD generation.
This commit is contained in:
47
Editor/Scripts/Editor/AssetDatabaseUtils.cs
Normal file
47
Editor/Scripts/Editor/AssetDatabaseUtils.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TAO.VertexAnimation.Editor
|
||||
{
|
||||
public static class AssetDatabaseUtils
|
||||
{
|
||||
public static bool HasChildAsset(Object parent, Object child)
|
||||
{
|
||||
var assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(parent));
|
||||
|
||||
foreach (var a in assets)
|
||||
{
|
||||
if (a == child)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void RemoveChildAssets(Object parent, Object[] filter = null)
|
||||
{
|
||||
var assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(parent));
|
||||
|
||||
foreach (var a in assets)
|
||||
{
|
||||
bool filterSkip = false;
|
||||
|
||||
foreach (var f in filter)
|
||||
{
|
||||
if (a == f)
|
||||
{
|
||||
filterSkip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!filterSkip && a != parent)
|
||||
{
|
||||
AssetDatabase.RemoveObjectFromAsset(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
Editor/Scripts/Editor/AssetDatabaseUtils.cs.meta
Normal file
11
Editor/Scripts/Editor/AssetDatabaseUtils.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d394aa43ff9889d45878e965ac0f1a30
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -68,6 +68,7 @@ namespace TAO.VertexAnimation.Editor
|
||||
using (new EditorGUILayout.VerticalScope())
|
||||
{
|
||||
EditorGUILayout.LabelField("General", EditorStyles.centeredGreyMiniLabel);
|
||||
EditorGUILayout.PropertyField(editorData.FindPropertyRelative("fps"));
|
||||
EditorGUILayout.PropertyField(editorData.FindPropertyRelative("maxFrames"));
|
||||
}
|
||||
}
|
||||
|
52
Editor/Scripts/ModelBaker/AnimationPrefab.cs
Normal file
52
Editor/Scripts/ModelBaker/AnimationPrefab.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TAO.VertexAnimation.Editor
|
||||
{
|
||||
public static class AnimationPrefab
|
||||
{
|
||||
public static GameObject Create(string path, string name, Mesh[] meshes, Material material, float[] lodTransitions)
|
||||
{
|
||||
// Create parent.
|
||||
GameObject parent = new GameObject(name, typeof(LODGroup), typeof(VA_AnimatorComponentAuthoring), typeof(Unity.Entities.ConvertToEntity));
|
||||
|
||||
// Create all LODs.
|
||||
LOD[] lods = new LOD[meshes.Length];
|
||||
|
||||
for (int i = 0; i < meshes.Length; i++)
|
||||
{
|
||||
GameObject lod = new GameObject(string.Format("{0}_LOD{1}", name, i), typeof(MeshFilter), typeof(MeshRenderer));
|
||||
|
||||
var mf = lod.GetComponent<MeshFilter>();
|
||||
mf.sharedMesh = meshes[i];
|
||||
var mr = lod.GetComponent<MeshRenderer>();
|
||||
mr.sharedMaterial = material;
|
||||
|
||||
lod.transform.SetParent(parent.transform);
|
||||
lods[i] = new LOD(lodTransitions[i], new Renderer[1] { mr });
|
||||
}
|
||||
|
||||
var lodGroup = parent.GetComponent<LODGroup>();
|
||||
lodGroup.SetLODs(lods);
|
||||
lodGroup.RecalculateBounds();
|
||||
|
||||
// Create prefab.
|
||||
GameObject prefab = PrefabUtility.SaveAsPrefabAssetAndConnect(parent, path, InteractionMode.AutomatedAction);
|
||||
GameObject.DestroyImmediate(parent);
|
||||
|
||||
return prefab;
|
||||
}
|
||||
|
||||
public static GameObject Create(string path, string name, Mesh[] meshes, Material material, AnimationCurve lodTransitions)
|
||||
{
|
||||
float[] lt = new float[meshes.Length];
|
||||
|
||||
for (int i = 0; i < lt.Length; i++)
|
||||
{
|
||||
lt[i] = lodTransitions.Evaluate((1.0f / lt.Length) * (i + 1));
|
||||
}
|
||||
|
||||
return Create(path, name, meshes, material, lt);
|
||||
}
|
||||
}
|
||||
}
|
11
Editor/Scripts/ModelBaker/AnimationPrefab.cs.meta
Normal file
11
Editor/Scripts/ModelBaker/AnimationPrefab.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b2f9ea47456fd24387722ab88de04c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -5,212 +5,87 @@ using System.Linq;
|
||||
|
||||
namespace TAO.VertexAnimation.Editor
|
||||
{
|
||||
[CustomEditor(typeof(VA_ModelBaker))]
|
||||
public class VA_ModelBakerEditor : UnityEditor.Editor
|
||||
{
|
||||
private VA_ModelBaker modelBaker = null;
|
||||
[CustomEditor(typeof(VA_ModelBaker))]
|
||||
public class VA_ModelBakerEditor : UnityEditor.Editor
|
||||
{
|
||||
private VA_ModelBaker modelBaker = null;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
modelBaker = target as VA_ModelBaker;
|
||||
}
|
||||
void OnEnable()
|
||||
{
|
||||
modelBaker = target as VA_ModelBaker;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
InputGUI();
|
||||
EditorGUILayoutUtils.HorizontalLine(color: Color.gray);
|
||||
BakeGUI();
|
||||
InputGUI();
|
||||
EditorGUILayoutUtils.HorizontalLine(color: Color.gray);
|
||||
BakeGUI();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
EditorGUILayoutUtils.HorizontalLine(color: Color.gray);
|
||||
OutputGUI();
|
||||
}
|
||||
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 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"));
|
||||
private void BakeGUI()
|
||||
{
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("saveBakedDataToAsset"));
|
||||
|
||||
int il = EditorGUI.indentLevel;
|
||||
if (modelBaker.saveBakedDataToAsset)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("generateAnimationBook"));
|
||||
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;
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("generateLODS"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("lodCurve"), new GUIContent(""));
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Bake", GUILayout.Height(32)))
|
||||
{
|
||||
ClearBakedData();
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("generatePrefab"));
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("materialShader"), new GUIContent(""));
|
||||
}
|
||||
}
|
||||
EditorGUI.indentLevel = il;
|
||||
|
||||
modelBaker.Bake();
|
||||
if (GUILayout.Button("Bake", GUILayout.Height(32)))
|
||||
{
|
||||
modelBaker.Bake();
|
||||
|
||||
if (modelBaker.saveBakedDataToAsset)
|
||||
{
|
||||
SaveBakedData();
|
||||
}
|
||||
}
|
||||
if (modelBaker.saveBakedDataToAsset)
|
||||
{
|
||||
modelBaker.SaveAssets();
|
||||
}
|
||||
}
|
||||
|
||||
if (modelBaker.BakedData.mesh != null)
|
||||
{
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Save", EditorStyles.miniButtonLeft))
|
||||
{
|
||||
SaveBakedData();
|
||||
}
|
||||
if (GUILayout.Button("Delete", EditorStyles.miniButtonRight))
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Delete Assets", "Deleting assets will loose references within the project.", "Ok", "Cancel"))
|
||||
{
|
||||
modelBaker.DeleteSavedAssets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
private void OutputGUI()
|
||||
{
|
||||
using (new EditorGUI.DisabledGroupScope(true))
|
||||
{
|
||||
EditorGUILayout.PropertyField(serializedObject.FindProperty("bakedData"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
169
Editor/Scripts/ModelBaker/VA_ModelBaker.cs
Normal file
169
Editor/Scripts/ModelBaker/VA_ModelBaker.cs
Normal file
@ -0,0 +1,169 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TAO.VertexAnimation.Editor
|
||||
{
|
||||
[CreateAssetMenu(fileName = "new ModelBaker", menuName = "VA_ModelBaker/ModelBaker", order = 400)]
|
||||
public class VA_ModelBaker : ScriptableObject
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// Input.
|
||||
public GameObject model;
|
||||
public AnimationClip[] animationClips;
|
||||
[Range(1, 60)]
|
||||
public int fps = 24;
|
||||
public int textureWidth = 512;
|
||||
|
||||
public bool generateLODS = true;
|
||||
public AnimationCurve lodCurve = new AnimationCurve(new Keyframe(0, 1), new Keyframe(1, 0.01f));
|
||||
public bool saveBakedDataToAsset = true;
|
||||
public bool generateAnimationBook = true;
|
||||
public bool generatePrefab = true;
|
||||
public Shader materialShader = null;
|
||||
|
||||
// Output.
|
||||
public GameObject prefab = null;
|
||||
public Material material = null;
|
||||
public Mesh[] meshes = null;
|
||||
public VA_AnimationBook book = null;
|
||||
|
||||
[SerializeField]
|
||||
private AnimationBaker.BakedData bakedData;
|
||||
|
||||
public void Bake()
|
||||
{
|
||||
var target = Instantiate(model);
|
||||
target.name = model.name;
|
||||
|
||||
target.ConbineAndConvertGameObject();
|
||||
bakedData = target.Bake(animationClips, fps, textureWidth);
|
||||
|
||||
if (generateLODS)
|
||||
{
|
||||
// TODO: LODs.
|
||||
meshes = new Mesh[1] { bakedData.mesh };
|
||||
}
|
||||
else
|
||||
{
|
||||
meshes = new Mesh[1] { bakedData.mesh };
|
||||
}
|
||||
|
||||
DestroyImmediate(target);
|
||||
}
|
||||
|
||||
public void SaveAssets()
|
||||
{
|
||||
AssetDatabaseUtils.RemoveChildAssets(this, new Object[2] { book, material });
|
||||
|
||||
// TODO: LODs
|
||||
AssetDatabase.AddObjectToAsset(bakedData.mesh, this);
|
||||
|
||||
foreach (var pm in bakedData.positionMaps)
|
||||
{
|
||||
AssetDatabase.AddObjectToAsset(pm, this);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
if (generatePrefab)
|
||||
{
|
||||
GeneratePrefab();
|
||||
}
|
||||
|
||||
if (generateAnimationBook)
|
||||
{
|
||||
GenerateBook();
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
public void DeleteSavedAssets()
|
||||
{
|
||||
// Remove assets.
|
||||
var assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(this));
|
||||
foreach (var a in assets)
|
||||
{
|
||||
if (a != this)
|
||||
{
|
||||
AssetDatabase.RemoveObjectFromAsset(a);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete prefab.
|
||||
string path = AssetDatabase.GetAssetPath(prefab);
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
|
||||
// Clear variables.
|
||||
prefab = null;
|
||||
material = null;
|
||||
meshes = null;
|
||||
book = null;
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
public void GeneratePrefab()
|
||||
{
|
||||
string path = AssetDatabase.GetAssetPath(this);
|
||||
int start = path.LastIndexOf('/');
|
||||
path = path.Remove(start, path.Length - start);
|
||||
path += "/" + name + ".prefab";
|
||||
|
||||
// Generate Material
|
||||
if (!AssetDatabaseUtils.HasChildAsset(this, material))
|
||||
{
|
||||
material = AnimationMaterial.Create(name, materialShader);
|
||||
AssetDatabase.AddObjectToAsset(material, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
material.shader = materialShader;
|
||||
}
|
||||
|
||||
// Generate Prefab
|
||||
prefab = AnimationPrefab.Create(path, name, meshes, material, lodCurve);
|
||||
}
|
||||
|
||||
public void GenerateBook()
|
||||
{
|
||||
if (!book)
|
||||
{
|
||||
book = CreateInstance<VA_AnimationBook>();
|
||||
}
|
||||
|
||||
book.name = string.Format("{0}Book", name);
|
||||
book.editorData = new VA_AnimationBook.EditorData
|
||||
{
|
||||
materials = new Material[1] { material }
|
||||
};
|
||||
|
||||
foreach (Texture2D tex in bakedData.positionMaps)
|
||||
{
|
||||
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 book);
|
||||
|
||||
if (!AssetDatabaseUtils.HasChildAsset(this, book))
|
||||
{
|
||||
AssetDatabase.AddObjectToAsset(book, this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
11
Editor/Scripts/ModelBaker/VA_ModelBaker.cs.meta
Normal file
11
Editor/Scripts/ModelBaker/VA_ModelBaker.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6752e365d065458469473b601e74e699
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -300,6 +300,13 @@ namespace TAO.VertexAnimation.Editor
|
||||
book.editorData.maxFrames = maxFrames;
|
||||
}
|
||||
}
|
||||
else if (p.StartsWith("FPS-"))
|
||||
{
|
||||
if (int.TryParse(p.Remove(0, 4), out int fps))
|
||||
{
|
||||
book.editorData.fps = fps;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
book.editorData.animationPages[i] = ap;
|
||||
@ -339,6 +346,7 @@ namespace TAO.VertexAnimation.Editor
|
||||
{
|
||||
book.playData = new VA_AnimationBook.PlayData
|
||||
{
|
||||
fps = book.editorData.fps,
|
||||
maxFrames = book.editorData.maxFrames,
|
||||
materials = book.editorData.materials
|
||||
};
|
||||
|
Reference in New Issue
Block a user