diff --git a/Editor/Scripts/Editor/VA_AnimationBookEditor.cs b/Editor/Scripts/Editor/VA_AnimationBookEditor.cs index 862cf01..816a04c 100644 --- a/Editor/Scripts/Editor/VA_AnimationBookEditor.cs +++ b/Editor/Scripts/Editor/VA_AnimationBookEditor.cs @@ -1,10 +1,5 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; +using UnityEngine; using UnityEditor; -using System.Runtime.CompilerServices; -using UnityEngine.Rendering.VirtualTexturing; -using System; namespace TAO.VertexAnimation.Editor { @@ -12,11 +7,12 @@ namespace TAO.VertexAnimation.Editor public class VA_AnimationBookEditor : UnityEditor.Editor { private VA_AnimationBook animationBook = null; - private Vector2 textireGroupScollPos; + private Vector2 textureGroupScollPos; private Vector2 animationPagesScollPos; private UnityEditor.Editor previewEditor = null; private int previewIndex = 0; + private int curviewIndex = 0; void OnEnable() { @@ -77,21 +73,26 @@ namespace TAO.VertexAnimation.Editor SerializedProperty textureGroups = serializedObject.FindProperty("textureGroups"); int removeWidth = 16; int nameWidth = 152; + int optionWidth = 110; int linearWidth = 50; using (new EditorGUILayout.VerticalScope()) { EditorGUILayout.LabelField("TextureGroups", EditorStyles.centeredGreyMiniLabel); - textireGroupScollPos = EditorGUILayout.BeginScrollView(textireGroupScollPos, false, false); + textureGroupScollPos = EditorGUILayout.BeginScrollView(textureGroupScollPos, false, false); using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar)) { EditorGUILayout.LabelField("", GUILayout.Width(removeWidth)); EditorGUILayout.LabelField("material parameter name", GUILayout.Width(nameWidth)); + EditorGUILayout.LabelField("texture type", GUILayout.Width(optionWidth)); + EditorGUILayout.LabelField("wrap mode", GUILayout.Width(optionWidth)); + EditorGUILayout.LabelField("filter mode", GUILayout.Width(optionWidth)); EditorGUILayout.LabelField("is linear", GUILayout.MinWidth(linearWidth)); } EditorGUILayout.EndScrollView(); + textureGroupScollPos = EditorGUILayout.BeginScrollView(textureGroupScollPos, false, false); for (int i = 0; i < textureGroups.arraySize; i++) { using (new EditorGUILayout.HorizontalScope()) @@ -103,9 +104,13 @@ namespace TAO.VertexAnimation.Editor } EditorGUILayout.PropertyField(textureGroups.GetArrayElementAtIndex(i).FindPropertyRelative("shaderParamName"), GUIContent.none, GUILayout.Width(nameWidth)); + EditorGUILayout.PropertyField(textureGroups.GetArrayElementAtIndex(i).FindPropertyRelative("textureType"), GUIContent.none, GUILayout.Width(optionWidth)); + EditorGUILayout.PropertyField(textureGroups.GetArrayElementAtIndex(i).FindPropertyRelative("wrapMode"), GUIContent.none, GUILayout.Width(optionWidth)); + EditorGUILayout.PropertyField(textureGroups.GetArrayElementAtIndex(i).FindPropertyRelative("filterMode"), GUIContent.none, GUILayout.Width(optionWidth)); EditorGUILayout.PropertyField(textureGroups.GetArrayElementAtIndex(i).FindPropertyRelative("isLinear"), GUIContent.none, GUILayout.MinWidth(linearWidth)); } } + EditorGUILayout.EndScrollView(); if (GUILayout.Button("+", EditorStyles.miniButton)) { @@ -161,7 +166,7 @@ namespace TAO.VertexAnimation.Editor SerializedProperty textures = animationPages.GetArrayElementAtIndex(i).FindPropertyRelative("textures"); for (int t = 0; t < textures.arraySize; t++) { - EditorGUILayout.PropertyField(textures.GetArrayElementAtIndex(t), GUIContent.none, GUILayout.MinWidth(textureWidth)); + EditorGUILayout.PropertyField(textures.GetArrayElementAtIndex(t).FindPropertyRelative("texture2D"), GUIContent.none, GUILayout.MinWidth(textureWidth)); } } } @@ -192,7 +197,16 @@ namespace TAO.VertexAnimation.Editor SerializedProperty texture2DArray = serializedObject.FindProperty("texture2DArray"); EditorGUILayout.LabelField("Texture2DArray", EditorStyles.centeredGreyMiniLabel); - previewIndex = EditorGUILayout.IntSlider(previewIndex, 0, texture2DArray.arraySize - 1); + + using (new EditorGUI.DisabledScope(true)) + { + for (int t = 0; t < texture2DArray.arraySize; t++) + { + EditorGUILayout.PropertyField(texture2DArray.GetArrayElementAtIndex(t), GUIContent.none); + } + } + + previewIndex = EditorGUILayout.IntSlider("Preview" ,previewIndex, 0, texture2DArray.arraySize - 1); } } } @@ -211,9 +225,10 @@ namespace TAO.VertexAnimation.Editor public override void OnPreviewGUI(Rect r, GUIStyle background) { - if (previewEditor == null) + if (previewEditor == null || curviewIndex != previewIndex) { - previewEditor = UnityEditor.Editor.CreateEditor(animationBook.texture2DArray[previewIndex]); + curviewIndex = previewIndex; + previewEditor = CreateEditor(animationBook.texture2DArray[previewIndex]); } previewEditor.OnInteractivePreviewGUI(r, background); diff --git a/Runtime/Scripts/VA_AnimationBook.cs b/Runtime/Scripts/VA_AnimationBook.cs index cabb3d7..e6f3044 100644 --- a/Runtime/Scripts/VA_AnimationBook.cs +++ b/Runtime/Scripts/VA_AnimationBook.cs @@ -8,7 +8,7 @@ namespace TAO.VertexAnimation public class VA_AnimationBook : ScriptableObject { public int maxFrames; - public List textureGroups = new List() { new TextureGroup { shaderParamName = "_PositionMap", isLinear = false } }; + public List textureGroups = new List() { new TextureGroup { shaderParamName = "_PositionMap", textureType = TextureType.AnimationMap, wrapMode = TextureWrapMode.Repeat, filterMode = FilterMode.Point, isLinear = false } }; public List animationPages = new List(); public Material[] materials; @@ -16,56 +16,138 @@ namespace TAO.VertexAnimation public void Create() { - // Create textures. - texture2DArray.Clear(); - foreach (var item in GetTextures()) + GenerateTextures(); + SetMaterials(); + } + + private void OnValidate() + { + // TODO: Check for naming conflicts and textures. + // TODO: Debug message box instead of debug logs. + } + + private void ReferenceDuplicates() + { + for (int i = 0; i < textureGroups.Count; i++) { - if(VA_Texture2DArrayUtils.IsValidForTextureArray(item.Value.ToArray())) + List t = new List(); + + for (int j = 0; j < animationPages.Count; j++) { - texture2DArray.Add(VA_Texture2DArrayUtils.CreateTextureArray(item.Value.ToArray(), false, textureGroups[item.Key].isLinear, TextureWrapMode.Repeat, FilterMode.Point, 1, name + "-" + item.Key.ToString())); + // Check if exist. + if (!t.Contains(animationPages[j].textures[i].texture2D)) + { + t.Add(animationPages[j].textures[i].texture2D); + } + + // Add index reference. + animationPages[j].textures[i].textureArrayIndex = t.IndexOf(animationPages[j].textures[i].texture2D); + } + } + } + + private void GenerateTextures() + { + ReferenceDuplicates(); + + texture2DArray.Clear(); + + for (int i = 0; i < textureGroups.Count; i++) + { + var t = GetTextures(i).ToArray(); + if (VA_Texture2DArrayUtils.IsValidForTextureArray(t)) + { + texture2DArray.Add(VA_Texture2DArrayUtils.CreateTextureArray(t, false, textureGroups[i].isLinear, textureGroups[i].wrapMode, textureGroups[i].filterMode, 1, name + textureGroups[i].shaderParamName)); + } + } + } + + private List GetTextures(int textureIndex) + { + List textures = new List(); + + foreach (var ap in animationPages) + { + // Check if exist. + if (!textures.Contains(ap.textures[textureIndex].texture2D)) + { + textures.Add(ap.textures[textureIndex].texture2D); } } - // Assign material parameters. - if(materials != null) + return textures; + } + + private void SetMaterials() + { + if (materials != null) { foreach (Material mat in materials) { - if(mat != null) + if (mat != null) { + if (mat.HasProperty("_MaxFrames")) + { + mat.SetFloat("_MaxFrames", maxFrames); + } + for (int i = 0; i < texture2DArray.Count; i++) { - mat.SetTexture(textureGroups[i].shaderParamName, texture2DArray[i]); + if (mat.HasProperty(textureGroups[i].shaderParamName)) + { + mat.SetTexture(textureGroups[i].shaderParamName, texture2DArray[i]); + } } } } } } - private void OnValidate() + public List GetAnimationData() { - foreach (var item in GetTextures()) - { - VA_Texture2DArrayUtils.IsValidForTextureArray(item.Value.ToArray()); + List data = new List(); + + foreach (var ap in animationPages) + { + data.Add(new VA_AnimationData + { + name = ap.name, + frames = ap.frames, + maxFrames = maxFrames, + frameTime = 1.0f / maxFrames, + duration = 1.0f / maxFrames * ap.frames, + animationMapIndex = GetFirstAnimationMapIndex(in ap.textures), + colorMapIndex = GetFirstColorMapIndex(in ap.textures) + }); } + + return data; } - private Dictionary> GetTextures() + private int GetFirstAnimationMapIndex(in List textures) { - Dictionary> dict = new Dictionary>(); - - // Group and collect the textures. for (int i = 0; i < textureGroups.Count; i++) { - dict.Add(i, new List()); - - for (int j = 0; j < animationPages.Count; j++) + if(textureGroups[i].textureType == TextureType.AnimationMap) { - dict[i].Add(animationPages[j].textures[i]); + return textures[i].textureArrayIndex; } } - return dict; + return -1; + } + + private int GetFirstColorMapIndex(in List textures) + { + for (int i = 0; i < textureGroups.Count; i++) + { + if (textureGroups[i].textureType == TextureType.ColorMap) + { + return textures[i].textureArrayIndex; + } + } + + return -1; } } @@ -74,13 +156,29 @@ namespace TAO.VertexAnimation { public string name; public int frames; - public List textures; + public List textures; } [System.Serializable] public struct TextureGroup { public string shaderParamName; + public TextureType textureType; + public TextureWrapMode wrapMode; + public FilterMode filterMode; public bool isLinear; } + + [System.Serializable] + public class TextureEntry + { + public Texture2D texture2D = null; + public int textureArrayIndex = -1; + } + + public enum TextureType + { + AnimationMap, + ColorMap + } } \ No newline at end of file diff --git a/Runtime/Scripts/VA_AnimationLibrary.cs b/Runtime/Scripts/VA_AnimationLibrary.cs index fb1bd05..a0c697a 100644 --- a/Runtime/Scripts/VA_AnimationLibrary.cs +++ b/Runtime/Scripts/VA_AnimationLibrary.cs @@ -33,22 +33,9 @@ namespace TAO.VertexAnimation if (animationBooks != null) { - for (int b = 0; b < animationBooks.Length; b++) + foreach (var ab in animationBooks) { - if(animationBooks[b].animationPages != null) - { - for (int p = 0; p < animationBooks[b].animationPages.Count; p++) - { - animations.Add(new VA_AnimationData - { - name = new Unity.Collections.FixedString32(animationBooks[b].animationPages[p].name), - maxFrames = animationBooks[b].maxFrames, - frames = animationBooks[b].animationPages[p].frames, - frameTime = 1.0f / animationBooks[b].maxFrames, - duration = 1.0f / animationBooks[b].maxFrames * animationBooks[b].animationPages[p].frames - }); - } - } + animations.AddRange(ab.GetAnimationData()); } } } diff --git a/Runtime/Scripts/VA_AnimationLibraryData.cs b/Runtime/Scripts/VA_AnimationLibraryData.cs index 30189dc..0982f54 100644 --- a/Runtime/Scripts/VA_AnimationLibraryData.cs +++ b/Runtime/Scripts/VA_AnimationLibraryData.cs @@ -6,13 +6,20 @@ namespace TAO.VertexAnimation [System.Serializable] public struct VA_AnimationData { + // The name of the animation. public FixedString32 name; + // The frames in this animation. public int frames; + // The maximum of frames the texture holds. public int maxFrames; // 1.0f / maxFrames. public float frameTime; - // frameTime * frames. + // FrameTime * frames. public float duration; + // The index of the related animation texture. + public int animationMapIndex; + // The index of the related color textures if/when added. + public int colorMapIndex; } public struct VA_AnimationLibraryData @@ -22,8 +29,8 @@ namespace TAO.VertexAnimation public static class VA_AnimationLibraryUtils { - public static int GetAnimation(ref VA_AnimationLibraryData animationsRef, FixedString32 animationName) - { + public static int GetAnimation(ref VA_AnimationLibraryData animationsRef, FixedString32 animationName) + { for (int i = 0; i < animationsRef.animations.Length; i++) { if (animationsRef.animations[i].name == animationName) @@ -32,7 +39,17 @@ namespace TAO.VertexAnimation } } - return -1; + return -1; } + + public static int GetAnimationMapIndex(ref VA_AnimationLibraryData animationsRef, int animation) + { + return animationsRef.animations[animation].animationMapIndex; + } + + public static int GetColorMapIndex(ref VA_AnimationLibraryData animationsRef, int animation) + { + return animationsRef.animations[animation].colorMapIndex; + } } } \ No newline at end of file diff --git a/Runtime/Scripts/VA_AnimatorComponentAuthoring.cs b/Runtime/Scripts/VA_AnimatorComponentAuthoring.cs index e3a2256..5755d0a 100644 --- a/Runtime/Scripts/VA_AnimatorComponentAuthoring.cs +++ b/Runtime/Scripts/VA_AnimatorComponentAuthoring.cs @@ -15,7 +15,8 @@ namespace TAO.VertexAnimation public struct VA_AnimatorComponent : IComponentData { public int animationIndex; - public int animationIndexSchedule; + // TODO: Animation blending. + //public int animationIndexSchedule; public float animationTime; public BlobAssetReference animationLibrary; } @@ -35,7 +36,7 @@ namespace TAO.VertexAnimation VA_AnimatorComponent animatorComponent = new VA_AnimatorComponent { animationIndex = 0, - animationIndexSchedule = -1, + //animationIndexSchedule = -1, animationTime = 0, animationLibrary = animLib }; @@ -47,12 +48,10 @@ namespace TAO.VertexAnimation { Entity ent = GetPrimaryEntity(children[i]); - VA_AnimationIndexComponent animationIndex = new VA_AnimationIndexComponent { Value = 0 }; - DstEntityManager.AddComponentData(ent, animationIndex); - VA_AnimationTimeComponent animationTime = new VA_AnimationTimeComponent { Value = 0 }; - DstEntityManager.AddComponentData(ent, animationTime); - } - }); + VA_AnimationDataComponent animationData = new VA_AnimationDataComponent(); + DstEntityManager.AddComponentData(ent, animationData); + } + }); } } } diff --git a/Runtime/Scripts/VA_AnimatorSystem.cs b/Runtime/Scripts/VA_AnimatorSystem.cs index 779d9bb..b1308fa 100644 --- a/Runtime/Scripts/VA_AnimatorSystem.cs +++ b/Runtime/Scripts/VA_AnimatorSystem.cs @@ -1,17 +1,15 @@ -using Unity.Collections; -using Unity.Entities; -using Unity.Rendering; +using Unity.Entities; using Unity.Transforms; using Unity.Mathematics; namespace TAO.VertexAnimation { + // System to update all the animations. public class VA_AnimatorSystem : SystemBase { protected override void OnUpdate() { - var atc = GetComponentDataFromEntity(false); - var aic = GetComponentDataFromEntity(false); + var animationData = GetComponentDataFromEntity(false); Entities.ForEach((ref VA_AnimatorComponent ac, in DynamicBuffer children) => { @@ -20,68 +18,23 @@ namespace TAO.VertexAnimation // Get child. Entity child = children[i].Value; - atc[child] = new VA_AnimationTimeComponent { Value = ac.animationTime }; + // Get the animation lib data. + ref VA_AnimationLibraryData animationsRef = ref ac.animationLibrary.Value; - //// Get a copy of the time Component of the child. - //VA_AnimationTimeComponent atcCopy = atc[child]; - //// Set new value. - //atcCopy.Value = ac.animationTime; - //// Update original. - //atc[child] = atcCopy; - - aic[child] = new VA_AnimationIndexComponent { Value = ac.animationIndex }; - - //VA_AnimationIndexComponent aicCopy = aic[child]; - //aicCopy.Value = ac.animationIndex; - //aic[child] = aicCopy; + animationData[child] = new VA_AnimationDataComponent + { + Value = new float4 + { + x = ac.animationTime, + y = VA_AnimationLibraryUtils.GetAnimationMapIndex(ref animationsRef, ac.animationIndex), + z = VA_AnimationLibraryUtils.GetColorMapIndex(ref animationsRef, ac.animationIndex), + w = 0 + } + }; } }) - .WithNativeDisableContainerSafetyRestriction(atc) - .WithNativeDisableContainerSafetyRestriction(aic) + .WithNativeDisableContainerSafetyRestriction(animationData) .ScheduleParallel(); } } - - // Example systems to update animation parameters. - [UpdateBefore(typeof(VA_AnimatorSystem))] - public class VA_AnimationTimeSystem : SystemBase - { - protected override void OnUpdate() - { - float deltaTime = UnityEngine.Time.deltaTime; - - Entities.ForEach((ref VA_AnimatorComponent ac) => - { - // Get the animation lib data. - ref VA_AnimationLibraryData animationsRef = ref ac.animationLibrary.Value; - - ac.animationTime += deltaTime; - - if (ac.animationTime > animationsRef.animations[ac.animationIndex].duration) - { - ac.animationTime = ac.animationTime - animationsRef.animations[ac.animationIndex].duration; - } - - }).ScheduleParallel(); - } - } - - [UpdateBefore(typeof(VA_AnimatorSystem))] - public class VA_AnimationIndexSystem : SystemBase - { - protected override void OnUpdate() - { - Entities.ForEach((Entity entity, ref VA_AnimatorComponent ac) => - { - // Get the animation lib data. - ref VA_AnimationLibraryData animationLib = ref ac.animationLibrary.Value; - - int animationIndex = VA_AnimationLibraryUtils.GetAnimation(ref animationLib, "Shoot"); - - //int index = entity.Index % 2; - //ac.animationIndex = index; - ac.animationIndex = animationIndex; - }).ScheduleParallel(); - } - } } \ No newline at end of file diff --git a/Runtime/Scripts/VA_MaterialComponentData.cs b/Runtime/Scripts/VA_MaterialComponentData.cs index e1bed34..d613526 100644 --- a/Runtime/Scripts/VA_MaterialComponentData.cs +++ b/Runtime/Scripts/VA_MaterialComponentData.cs @@ -1,17 +1,13 @@ using Unity.Entities; +using Unity.Mathematics; using Unity.Rendering; namespace TAO.VertexAnimation { - [MaterialProperty("_AnimationIndex", MaterialPropertyFormat.Float)] - public struct VA_AnimationIndexComponent : IComponentData + [MaterialProperty("_AnimationData", MaterialPropertyFormat.Float4)] + public struct VA_AnimationDataComponent : IComponentData { - public float Value; - } - - [MaterialProperty("_AnimationTime", MaterialPropertyFormat.Float)] - public struct VA_AnimationTimeComponent : IComponentData - { - public float Value; + // animationTime, animationIndex, colorIndex, nan. + public float4 Value; } } \ No newline at end of file diff --git a/Runtime/Shaders/HLSL/VertexAnimation.hlsl b/Runtime/Shaders/HLSL/VertexAnimation.hlsl index d445238..c1e778f 100644 --- a/Runtime/Shaders/HLSL/VertexAnimation.hlsl +++ b/Runtime/Shaders/HLSL/VertexAnimation.hlsl @@ -12,10 +12,10 @@ float2 VA_UV_float(float2 uv, int maxFrames, float time) float timeInFrames = frac(time); timeInFrames = ceil(timeInFrames * maxFrames); timeInFrames /= maxFrames; - timeInFrames += (1 / maxFrames); + timeInFrames += round(1.0f / maxFrames); uvPosition.x = uv.x; - uvPosition.y = (1 - (timeInFrames)) + (1 - (1 - uv.y)); + uvPosition.y = (1.0f - (timeInFrames)) + (1.0f - (1.0f - uv.y)); return uvPosition; } diff --git a/Runtime/Shaders/SubGraphs/SampleTexture2dArrayLOD.shadersubgraph b/Runtime/Shaders/SubGraphs/SampleTexture2dArrayLOD.shadersubgraph index 2911038..b0e8365 100644 --- a/Runtime/Shaders/SubGraphs/SampleTexture2dArrayLOD.shadersubgraph +++ b/Runtime/Shaders/SubGraphs/SampleTexture2dArrayLOD.shadersubgraph @@ -245,7 +245,7 @@ "m_Id": "5ff96695f49e4d1182cf67a53de68be6" }, { - "m_Id": "6cb7d5a539a9483598c17e29f13c9871" + "m_Id": "f6f46ec323d94a088f47d6ed87a8560e" } ], "m_Precision": 0, @@ -272,6 +272,31 @@ "m_StageCapability": 3 } +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", + "m_ObjectId": "4a5cf08366814dfbb54e1ab1eacf2e33", + "m_Id": 1, + "m_DisplayName": "RGBA", + "m_SlotType": 0, + "m_Priority": 2147483647, + "m_Hidden": false, + "m_ShaderOutputName": "RGBA", + "m_StageCapability": 3, + "m_Value": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + }, + "m_DefaultValue": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 0.0 + } +} + { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.Internal.Texture2DArrayShaderProperty", @@ -446,24 +471,6 @@ } } -{ - "m_SGVersion": 0, - "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", - "m_ObjectId": "6cb7d5a539a9483598c17e29f13c9871", - "m_Id": 5, - "m_DisplayName": "LOD", - "m_SlotType": 0, - "m_Priority": 2147483647, - "m_Hidden": false, - "m_ShaderOutputName": "LOD", - "m_StageCapability": 3, - "m_Value": 0.0, - "m_DefaultValue": 0.0, - "m_Labels": [ - "X" - ] -} - { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.SamplerStateMaterialSlot", @@ -627,7 +634,7 @@ }, "m_Slots": [ { - "m_Id": "d2d519a5c5484c799973056f62d350a2" + "m_Id": "4a5cf08366814dfbb54e1ab1eacf2e33" } ], "m_Precision": 0, @@ -656,31 +663,6 @@ ] } -{ - "m_SGVersion": 0, - "m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot", - "m_ObjectId": "d2d519a5c5484c799973056f62d350a2", - "m_Id": 1, - "m_DisplayName": "Out_Vector4", - "m_SlotType": 0, - "m_Priority": 2147483647, - "m_Hidden": false, - "m_ShaderOutputName": "OutVector4", - "m_StageCapability": 3, - "m_Value": { - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 0.0 - }, - "m_DefaultValue": { - "x": 0.0, - "y": 0.0, - "z": 0.0, - "w": 0.0 - } -} - { "m_SGVersion": 0, "m_Type": "UnityEditor.ShaderGraph.PropertyNode", @@ -739,3 +721,21 @@ } } +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "f6f46ec323d94a088f47d6ed87a8560e", + "m_Id": 5, + "m_DisplayName": "LOD", + "m_SlotType": 0, + "m_Priority": 2147483647, + "m_Hidden": false, + "m_ShaderOutputName": "LOD", + "m_StageCapability": 3, + "m_Value": 0.0, + "m_DefaultValue": 0.0, + "m_Labels": [ + "X" + ] +} +