private static void CreateMaterial(MeshAnimationAsset asset)
        {
            var materialAssetName = asset.name + " Material";

            if (asset.bakedMaterial == null)
            {
                var material = new Material(asset.shader)
                {
                    name = materialAssetName
                };
                asset.bakedMaterial = material;
                AssetDatabase.AddObjectToAsset(material, asset);
            }
            else
            {
                asset.bakedMaterial.shader = asset.shader;
                asset.bakedMaterial.name   = materialAssetName;
            }

            if (asset.materialPreset != null)
            {
                var preset = new Preset(asset.materialPreset);
                if (preset.CanBeAppliedTo(asset.bakedMaterial))
                {
                    preset.ApplyTo(asset.bakedMaterial);
                }

                Object.DestroyImmediate(preset);
            }
        }
Beispiel #2
0
        public static void Bake([NotNull] MeshAnimationAsset asset)
        {
            if (asset == null)
            {
                throw new ArgumentNullException(nameof(asset));
            }

            var error = asset.GetValidationMessage();

            if (error != null)
            {
                throw new InvalidOperationException(error);
            }

            try
            {
                AssetDatabase.DisallowAutoRefresh();
                EditorUtility.DisplayProgressBar("Mesh Animator", "Baking", 0f);

                DestroyObject(ref asset.bakedTexture);
                CreateTexture(asset, out var aborted);
                if (!aborted)
                {
                    CreateMaterial(asset);
                    BakeAnimations(asset);
                }

                SaveAsset(asset);
            }
            finally
            {
                EditorUtility.ClearProgressBar();
                AssetDatabase.AllowAutoRefresh();
            }
        }
Beispiel #3
0
        public static void Play(this MeshAnimationAsset asset,
                                MaterialPropertyBlock block,
                                string animationName,
                                float speed          = 1f,
                                float?normalizedTime = 0f)
        {
            MeshAnimationAsset.AnimationData data = null;

            foreach (var animationData in asset.animationData)
            {
                if (animationData.name != animationName)
                {
                    continue;
                }

                data = animationData;
                break;
            }

            if (data == null)
            {
                return;
            }

            var start  = data.startFrame;
            var length = data.lengthFrames;
            var s      = speed / Mathf.Max(data.lengthSeconds, 0.01f);
            var time   = normalizedTime.HasValue
                ? Time.timeSinceLevelLoad + Mathf.Clamp01(normalizedTime.Value) * data.lengthSeconds
                : block.GetVector(AnimationTimeProp).z;

            block.SetFloat(AnimationLoopProp, data.looping ? 1 : 0);
            block.SetVector(AnimationTimeProp, new Vector4(start, length, s, time));
        }
Beispiel #4
0
        private static void SaveAsset(MeshAnimationAsset asset)
        {
            EditorUtility.SetDirty(asset);

            var assetPath = AssetDatabase.GetAssetPath(asset);

            AssetDatabase.ImportAsset(assetPath,
                                      ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }
Beispiel #5
0
        public static void Clear([NotNull] MeshAnimationAsset asset)
        {
            if (asset == null)
            {
                throw new ArgumentNullException(nameof(asset));
            }

            DestroyObject(ref asset.bakedMaterial);
            DestroyObject(ref asset.bakedTexture);
            SaveAsset(asset);
        }
        private static void CreateExtraMaterials(MeshAnimationAsset asset)
        {
            foreach (var extra in asset.extraMaterials)
            {
                var data = asset.extraMaterialData.Find(it => it.name == extra.name);
                if (data == null)
                {
                    data = new MeshAnimationAsset.ExtraMaterialData
                    {
                        name = extra.name
                    };
                    asset.extraMaterialData.Add(data);
                }

                if (data.material == null)
                {
                    data.material = new Material(asset.shader)
                    {
                        name = $"{asset.name}_{extra.name} Material"
                    };
                    AssetDatabase.AddObjectToAsset(data.material, asset);
                }

                data.material.shader = asset.shader;

                if (extra.preset != null)
                {
                    var preset = new Preset(extra.preset);
                    if (preset.CanBeAppliedTo(data.material))
                    {
                        preset.ApplyTo(data.material);
                    }

                    Object.DestroyImmediate(preset);
                }
            }

            foreach (var data in asset.extraMaterialData)
            {
                if (asset.extraMaterials.Any(extra => extra.name == data.name))
                {
                    continue;
                }

                Object.DestroyImmediate(data.material, true);

                data.material = null;
            }

            asset.extraMaterialData.RemoveAll(it => it.material == null);
        }
Beispiel #7
0
 private static void CreateMaterial(MeshAnimationAsset asset)
 {
     if (asset.bakedMaterial == null)
     {
         var material = new Material(asset.shader)
         {
             name = asset.name + " Material"
         };
         asset.bakedMaterial = material;
         AssetDatabase.AddObjectToAsset(material, asset);
     }
     else
     {
         asset.bakedMaterial.shader = asset.shader;
     }
 }
Beispiel #8
0
        public static void Play(this MeshAnimationAsset asset,
                                MaterialPropertyBlock block,
                                string animationName,
                                float speed = 1f,
                                float time  = 0f)
        {
            var data = asset.animationData.Find(d => d.clip.name == animationName);

            var start  = data.startFrame;
            var length = data.lengthFrames;

            speed  = Mathf.Max(0.01f, speed);
            speed /= Mathf.Max(data.clip.length, 0.01f);

            block.SetVector(AnimationTimeProp, new Vector4(start, length, speed, time));
        }
Beispiel #9
0
        private static void CreateTexture(MeshAnimationAsset asset, out bool aborted)
        {
            aborted = false;

            if (asset.bakedTexture == null)
            {
                var mesh        = asset.skin.GetComponentInChildren <SkinnedMeshRenderer>().sharedMesh;
                var vertexCount = mesh.vertexCount;
                var framesCount = asset.animationClips.Sum(clip => clip.GetFramesCount() + 1);

                if (vertexCount > 2048)
                {
                    var msg = $"WARNING: Mesh contains too many vertices ({vertexCount})";
                    if (!EditorUtility.DisplayDialog("Mesh Animator", msg, "Continue", "Abort"))
                    {
                        aborted = true;
                        return;
                    }
                }

                if (framesCount > 2048)
                {
                    var msg = $"WARNING: Mesh contains too many animation frames ({vertexCount})";
                    if (!EditorUtility.DisplayDialog("Mesh Animator", msg, "Continue", "Abort"))
                    {
                        aborted = true;
                        return;
                    }
                }

                var texWidth   = Mathf.NextPowerOfTwo(vertexCount);
                var textHeight = Mathf.NextPowerOfTwo(framesCount);

                var texture = new Texture2D(texWidth, textHeight, TextureFormat.RGB24, false)
                {
                    name      = asset.name + " Texture",
                    hideFlags = HideFlags.NotEditable,
                    wrapMode  = TextureWrapMode.Repeat,
                };

                AssetDatabase.AddObjectToAsset(texture, asset);
                asset.bakedTexture = texture;
            }
        }
        public static void Clear([NotNull] MeshAnimationAsset asset)
        {
            if (asset == null)
            {
                throw new ArgumentNullException(nameof(asset));
            }

            DestroyObject(ref asset.bakedMaterial);
            DestroyObject(ref asset.bakedTexture);

            foreach (var data in asset.extraMaterialData)
            {
                DestroyObject(ref data.material);
            }

            asset.extraMaterialData = new List <MeshAnimationAsset.ExtraMaterialData>();
            asset.animationData     = new List <MeshAnimationAsset.AnimationData>();

            SaveAsset(asset);
        }
Beispiel #11
0
        private static void BakeAnimations(MeshAnimationAsset asset)
        {
            var bakeObject = Object.Instantiate(asset.skin.gameObject);

            bakeObject.hideFlags = HideFlags.HideAndDontSave;
            var bakeMesh = new Mesh {
                hideFlags = HideFlags.HideAndDontSave
            };
            var skin = bakeObject.GetComponentInChildren <SkinnedMeshRenderer>();

            var bakeTransform = bakeObject.transform;

            bakeTransform.localPosition = Vector3.zero;
            bakeTransform.localRotation = Quaternion.identity;
            bakeTransform.localScale    = Vector3.one;

            var boundMin = Vector3.zero;
            var boundMax = Vector3.zero;

            var animator = bakeObject.GetComponent <Animator>();

            if (animator != null && animator.runtimeAnimatorController == null)
            {
                Debug.LogError("animator != null && animator.runtimeAnimatorController == null");
                return;
            }

            asset.animationData.Clear();

            AnimationMode.StartAnimationMode();
            AnimationMode.BeginSampling();

            try
            {
                foreach (var clip in asset.animationClips)
                {
                    for (int frame = 0, framesCount = clip.GetFramesCount(); frame < framesCount; frame++)
                    {
                        EditorUtility.DisplayProgressBar("Mesh Animator", clip.name, 1f * frame / framesCount);

                        AnimationMode.SampleAnimationClip(bakeObject, clip, frame / clip.frameRate);
                        skin.BakeMesh(bakeMesh);

                        var vertices = bakeMesh.vertices;
                        foreach (var vertex in vertices)
                        {
                            boundMin = Vector3.Min(boundMin, vertex);
                            boundMax = Vector3.Max(boundMax, vertex);
                        }
                    }
                }

                int globalFrame = 0;
                foreach (var clip in asset.animationClips)
                {
                    var framesCount = clip.GetFramesCount();
                    var looping     = clip.isLooping;

                    asset.animationData.Add(new MeshAnimationAsset.AnimationData
                    {
                        name          = clip.name,
                        startFrame    = globalFrame,
                        lengthFrames  = framesCount,
                        lengthSeconds = clip.length,
                        looping       = looping,
                    });

                    for (int frame = 0; frame < framesCount; frame++)
                    {
                        EditorUtility.DisplayProgressBar("Mesh Animator", clip.name, 1f * frame / framesCount);

                        AnimationMode.SampleAnimationClip(bakeObject, clip, frame / clip.frameRate);
                        skin.BakeMesh(bakeMesh);

                        CaptureMeshToTexture(asset.bakedTexture, bakeMesh, boundMin, boundMax, globalFrame);

                        if (looping && frame == 0)
                        {
                            CaptureMeshToTexture(asset.bakedTexture, bakeMesh, boundMin, boundMax,
                                                 globalFrame + framesCount);
                        }
                        else if (!looping && frame == framesCount - 1)
                        {
                            CaptureMeshToTexture(asset.bakedTexture, bakeMesh, boundMin, boundMax, globalFrame + 1);
                        }

                        ++globalFrame;
                    }

                    ++globalFrame;
                }

                while (globalFrame < asset.bakedTexture.height)
                {
                    CaptureMeshToTexture(asset.bakedTexture, bakeMesh, boundMin, boundMax, globalFrame);
                    ++globalFrame;
                }
            }
            finally
            {
                AnimationMode.EndSampling();
                AnimationMode.StopAnimationMode();
            }

            Object.DestroyImmediate(bakeObject);
            Object.DestroyImmediate(bakeMesh);

            asset.bakedMaterial.SetTexture(AnimTextureProp, asset.bakedTexture);
            asset.bakedMaterial.SetVector(AnimationMulProp, boundMax - boundMin);
            asset.bakedMaterial.SetVector(AnimationAddProp, boundMin);
        }