/// <summary>
            /// Compares the properties and curves of two animation clips.
            /// </summary>
            /// <param name="animClipOriginal">Animation clip original.</param>
            /// <param name="animClipImported">Animation clip imported.</param>
            public static void ClipTest(AnimationClip animClipOriginal, AnimationClip animClipImported)
            {
                // check clip properties match
                AnimTester.ClipPropertyTest(animClipOriginal, animClipImported);

                foreach (EditorCurveBinding curveBinding in AnimationUtility.GetCurveBindings(animClipOriginal))
                {
                    foreach (EditorCurveBinding impCurveBinding in AnimationUtility.GetCurveBindings(animClipImported))
                    {
                        // only compare if the path and property names match
                        if (curveBinding.path != impCurveBinding.path || curveBinding.propertyName != impCurveBinding.propertyName)
                        {
                            continue;
                        }

                        bool isRotation = AnimationTestDataClass.m_rotationEulerNames.Contains(curveBinding.propertyName) ||
                                          AnimationTestDataClass.m_rotationQuaternionNames.Contains(curveBinding.propertyName);

                        AnimationCurve animCurveOrig = AnimationUtility.GetEditorCurve(animClipOriginal, curveBinding);
                        Assert.That(animCurveOrig, Is.Not.Null);

                        AnimationCurve animCurveImported = AnimationUtility.GetEditorCurve(animClipImported, impCurveBinding);
                        Assert.That(animCurveImported, Is.Not.Null);

                        AnimTester.KeyValuesTest(
                            animCurveImported,
                            animCurveOrig,
                            string.Format("path: {0}, property: {1}", curveBinding.path, curveBinding.propertyName),
                            isRotation);
                    }
                }
            }
        public int ContinuousRotationAnimTest(RotationCurveType rotCurveType, float [] keyTimesInSeconds, Vector3 [] keyEulerValues)
        {
            System.Type componentType = typeof(Transform);

            string[] propertyNames       = null;
            string   testName            = componentType.ToString() + "_ContinuousRotations";
            bool     compareOriginalKeys = false;

            switch (rotCurveType)
            {
            case RotationCurveType.kEuler:
                testName     += "_Euler";
                propertyNames = AnimationTestDataClass.m_rotationEulerNames.ToArray();
                break;

            case RotationCurveType.kQuaternion:
                compareOriginalKeys = true;
                testName           += "_Quaternion";
                propertyNames       = AnimationTestDataClass.m_rotationQuaternionNames.ToArray();
                break;
            }

            KeyData keyData = new TransformKeyData {
                importSettings      = new { resampleCurves = false, animationType = ModelImporterAnimationType.Legacy, animationCompression = ModelImporterAnimationCompression.Off, importConstraints = true },
                compareOriginalKeys = compareOriginalKeys, RotationType = rotCurveType, propertyNames = propertyNames, componentType = componentType, keyTimes = keyTimesInSeconds, keyEulerValues = keyEulerValues
            };

            var tester = new AnimTester {
                keyData = keyData, testName = testName, path = GetRandomFbxFilePath()
            };

            return(tester.DoIt());
        }
        public void LegacySkinnedMeshAnimTest(string fbxPath)
        {
            fbxPath = FindPathInUnitTests(fbxPath);
            Assert.That(fbxPath, Is.Not.Null);

            // add fbx to scene
            GameObject originalGO = AddAssetToScene(fbxPath);

            // get clip
            AnimationClip animClipOriginal = originalGO.GetComponentInChildren <Animation>().clip;

            Assert.That(animClipOriginal, Is.Not.Null);

            // export fbx
            // get GameObject
            string filename = AssetDatabase.GetAssetPath(ExportToFbx(originalGO));

            // TODO: Uni-34492 change importer settings of (newly exported model)
            // so that it's not resampled and it is legacy animation
            AnimTester.ConfigureImportSettings(filename);

            var animClipImported = AnimTester.GetClipFromFbx(filename);

            AnimTester.ClipTest(animClipOriginal, animClipImported);
        }
Example #4
0
        public int BlendshapeAnimTest(float [] keyTimesInSeconds, float [] keyValues, System.Type componentType, string componentName)
        {
            var prefabPath = FindPathInUnitTests("Models/blendshape.fbx");

            Assert.That(prefabPath, Is.Not.Null);

            // add prefab to scene
            GameObject originalGO = AddAssetToScene(prefabPath);

            KeyData keyData = new PropertyKeyData {
                targetObject   = originalGO,
                propertyName   = componentName,
                componentType  = componentType,
                keyTimes       = keyTimesInSeconds,
                keyFloatValues = keyValues
            };

            var tester = new AnimTester {
                keyData = keyData, testName = componentName, path = GetRandomFbxFilePath()
            };

            var exportOptions = new ExportModelSettingsSerialize();

            exportOptions.SetAnimatedSkinnedMesh(true);

            tester.exportOptions = exportOptions;
            return(tester.DoIt());
        }
            /// <summary>
            /// Compares the properties and curves of multiple animation clips
            /// </summary>
            /// <param name="animClipsOriginal">Animation clips original.</param>
            /// <param name="animClipsImported">Animation clips imported.</param>
            public static void MultiClipTest(AnimationClip[] animClipsOriginal, Dictionary <string, AnimationClip> animClipsImported)
            {
                Assert.That(animClipsImported.Count, Is.EqualTo(animClipsOriginal.Length));

                foreach (var clip in animClipsOriginal)
                {
                    Assert.That(animClipsImported.ContainsKey(clip.name));
                    var fbxClip = animClipsImported [clip.name];
                    AnimTester.ClipTest(clip, fbxClip);
                }
            }
        public int GimbalConditionsAnimTest(float [] keyTimesInSeconds, Vector3 [] keyValues, System.Type componentType, string [] componentNames)
        {
            KeyData keyData = new QuaternionKeyData {
                propertyNames = componentNames, componentType = componentType, keyTimes = keyTimesInSeconds, keyEulerValues = keyValues
            };

            var tester = new AnimTester {
                keyData = keyData, testName = componentType.ToString() + "_Gimbal", path = GetRandomFbxFilePath()
            };

            return(tester.DoIt());
        }
        public int QuaternionPropertyAnimTest(float [] keyTimesInSeconds, Vector3 [] keyValues, System.Type componentType, string[] componentNames)
        {
            KeyData keyData = new QuaternionKeyData {
                compareOriginalKeys = true, propertyNames = componentNames, componentType = componentType, keyTimes = keyTimesInSeconds, keyEulerValues = keyValues
            };

            var tester = new AnimTester {
                keyData = keyData, testName = (componentType.ToString() + "_Quaternion"), path = GetRandomFbxFilePath()
            };

            return(tester.DoIt());
        }
        public int SimplePropertyAnimTest(float [] keyTimesInSeconds, float [] keyValues, System.Type componentType, string componentName)
        {
            KeyData keyData = new PropertyKeyData {
                propertyName = componentName, componentType = componentType, keyTimes = keyTimesInSeconds, keyFloatValues = keyValues
            };

            var tester = new AnimTester {
                keyData = keyData, testName = componentName, path = GetRandomFbxFilePath()
            };

            return(tester.DoIt());
        }
        public void AnimOnlyExportTest(string prefabPath)
        {
            prefabPath = FindPathInUnitTests(prefabPath);
            Assert.That(prefabPath, Is.Not.Null);

            // add prefab to scene
            GameObject originalGO = AddAssetToScene(prefabPath);

            // get clips
            var animator  = originalGO.GetComponentInChildren <Animator> ();
            var animClips = GetClipsFromAnimator(animator);

            // get the set of GameObject transforms to be exported with the clip
            var animatedObjects = GetAnimatedGameObjects(animClips, animator.gameObject);

            // export fbx
            // get GameObject
            GameObject fbxObj = ExportToFbx(originalGO, true);

            Assert.IsTrue(fbxObj);

            // compare hierarchy matches animated objects
            var s = new Stack <Transform> ();

            // don't check the root since it probably won't have the same name anyway
            foreach (Transform child in fbxObj.transform)
            {
                s.Push(child);
            }
            while (s.Count > 0)
            {
                var transform = s.Pop();

                Assert.That(animatedObjects.Contains(transform.name));
                animatedObjects.Remove(transform.name);

                foreach (Transform child in transform)
                {
                    s.Push(child);
                }
            }

            // compare clips
            var fbxAnimClips = AnimTester.GetClipsFromFbx(AssetDatabase.GetAssetPath(fbxObj));

            AnimTester.MultiClipTest(animClips, fbxAnimClips);
        }
Example #10
0
    static void Init(bool setMaxSize)
    {
        // Get existing open window or if none, make a new one:
        AnimTester wnd = EditorWindow.GetWindow <AnimTester> (false, "Anim Tester");

        //restrict size
        Object[] activeGOs = Selection.GetFiltered(typeof(Animation), SelectionMode.Editable | SelectionMode.TopLevel);

        wnd.minSize = new Vector2(500, 75 + activeGOs.Length * 20);

        if (setMaxSize)
        {
            wnd.maxSize = new Vector2(500, GetMaxHeight(activeGOs.Length));                     //75.1, because when the values are exactly the same, the window doesn't have a border which is ugly

//		if (wnd.docked == false)										//wnd.docked is unfortunately inaccessible
            wnd.maxSize = new Vector2(4000, 4000);                                                      //setting back to defaults (after formatting the window size) to allow window resizing which is good for docked windows (otherwise will resize the parent)
        }
    }
        public int ComponentAnimTest(System.Type componentType)
        {
            #if DEBUG_UNITTEST
            Debug.Log(string.Format("ComponentAnimTest {0}", componentType.ToString()));
            #endif

            if (!ModelExporter.MapsToFbxObject.ContainsKey(componentType))
            {
                #if DEBUG_UNITTEST
                Debug.Log(string.Format("skipping {0}; fbx export not supported", componentType.ToString()));
                #endif
                return(1);
            }

            string     testName     = "ComponentAnimTest_" + componentType.ToString();
            GameObject targetObject = AnimTester.CreateTargetObject(testName, componentType);

            string [] propertyNames =
                (from b in AnimationUtility.GetAnimatableBindings(targetObject, targetObject)
                 where b.type == componentType select b.propertyName).ToArray();

            if (propertyNames.Length == 0)
            {
                #if DEBUG_UNITTEST
                Debug.Log(string.Format("skipping {0}; no animatable Single properties found", componentType.ToString()));
                #endif
                return(1);
            }

            float [] keyTimesInSeconds = new float [3] {
                1f, 2f, 3f
            };
            var      ran       = new System.Random();
            float [] keyValues = Enumerable.Range(1, keyTimesInSeconds.Length).Select(x => (float)ran.NextDouble()).ToArray();

            KeyData keyData = new MultiPropertyKeyData {
                propertyNames = propertyNames, componentType = componentType, keyTimes = keyTimesInSeconds, keyValues = keyValues, targetObject = targetObject
            };

            var tester = new AnimTester {
                keyData = keyData, testName = testName, path = GetRandomFbxFilePath()
            };
            return(tester.DoIt() <= propertyNames.Length ? 1 : 0);
        }
Example #12
0
    //
    private void RefreshContent()
    {
        //we have to do this bullsh*t because the wnd.docked is inaccessible and we need to know whether we can set the max size or not (i.e. guess if it's docked or custom sized)
        bool setMaxSize = true;

        AnimTester wnd = EditorWindow.GetWindow <AnimTester> (false, "Anim Tester");

        if (m_EditableObjects == null || m_EditableObjects.Length <= 0)
        {
            setMaxSize = false;
        }
        else if (wnd.position.height > GetMaxHeight(m_EditableObjects.Length))
        {
            setMaxSize = false;
        }

        //reinit the window and its content
        Init(setMaxSize);
        InitObjects();
        this.Repaint();
    }
            public int Main(KeyData keyData, string testName, string path)
            {
                if (!keyData.targetObject)
                {
                    keyData.targetObject = CreateTargetObject(testName, keyData.componentType);
                }

                Animation animOrig = keyData.targetObject.AddComponent(typeof(Animation)) as Animation;

                AnimationClip animClipOriginal   = new AnimationClip();
                var           animCurvesOriginal = new AnimationCurve[keyData.NumProperties];

                animClipOriginal.legacy = true;
                animClipOriginal.name   = "anim_" + testName;

                for (int id = 0; id < keyData.NumProperties; id++)
                {
                    // initialize keys
                    Keyframe [] keys = new Keyframe [keyData.NumKeys];

                    for (int idx = 0; idx < keyData.NumKeys; idx++)
                    {
                        keys [idx].time  = keyData.keyTimes [idx];
                        keys [idx].value = keyData.GetKeyValues(id) [idx];
                    }
                    animCurvesOriginal[id] = new AnimationCurve(keys);

                    animClipOriginal.SetCurve("", keyData.componentType, keyData.GetPropertyName(id), animCurvesOriginal[id]);
                }

                animOrig.AddClip(animClipOriginal, animClipOriginal.name);
                animOrig.clip = animClipOriginal;

                // NOTE: when we first cached the curves the tangents wheren't set.
                foreach (EditorCurveBinding curveBinding in AnimationUtility.GetCurveBindings(animOrig.clip))
                {
                    int id = keyData.GetIndexOf(curveBinding.propertyName);
                    if (id == -1)
                    {
                        continue;
                    }

                    animCurvesOriginal[id] = AnimationUtility.GetEditorCurve(animOrig.clip, curveBinding);
                }

                // TODO: add extra parent so that we can test export/import of transforms
                var goRoot = new GameObject();

                goRoot.name = "Root_" + testName;
                keyData.targetObject.transform.parent = goRoot.transform;

                //export the object
                var exportedFilePath = ModelExporter.ExportObject(path, goRoot);

                Assert.That(exportedFilePath, Is.EqualTo(path));

                // TODO: Uni-34492 change importer settings of (newly exported model)
                // so that it's not resampled and it is legacy animation
                AnimTester.ConfigureImportSettings(path, keyData.importSettings);

                // create a scene GO so we can compare.
                #if DEBUG_UNITTEST
                GameObject prefabGO = AssetDatabase.LoadMainAssetAtPath(path) as GameObject;
                GameObject sceneGO  = Object.Instantiate(prefabGO, keyData.targetObject.transform.localPosition, keyData.targetObject.transform.localRotation);
                sceneGO.name = "Imported_" + testName;
                #endif

                //acquire imported object from exported file
                AnimationClip animClipImported = GetClipFromFbx(path);

                ClipPropertyTest(animClipOriginal, animClipImported);

                int result = 0;

                foreach (EditorCurveBinding curveBinding in AnimationUtility.GetCurveBindings(animClipImported))
                {
                    AnimationCurve animCurveImported = AnimationUtility.GetEditorCurve(animClipImported, curveBinding);
                    Assert.That(animCurveImported, Is.Not.Null);

                    string propertyBinding = curveBinding.propertyName;
                    int    id = keyData.GetIndexOf(propertyBinding);

                    bool hasQuatBinding =
                        MapEulerToQuaternionPropertyName.TryGetValue(propertyBinding, out propertyBinding);

                    bool isRotation = AnimationTestDataClass.m_rotationEulerNames.Contains(curveBinding.propertyName) ||
                                      AnimationTestDataClass.m_rotationQuaternionNames.Contains(curveBinding.propertyName);

                    if (id == -1)
                    {
                        id = keyData.GetIndexOf(propertyBinding);
                    }

                    #if DEBUG_UNITTEST
                    Debug.Log(string.Format("propertyBinding={0} mappedBinding={1} id={2}", curveBinding.propertyName, propertyBinding, id));
                    #endif

                    if (id != -1)
                    {
                        if (keyData.compareOriginalKeys)
                        {
                            // NOTE: we cannot compare the keys that exported quaternion but are imported as euler.
                            if (!hasQuatBinding)
                            {
                                // compare against original keydata
                                KeysTest(keyData.keyTimes, keyData.GetKeyValues(id), animCurveImported, curveBinding.propertyName);

                                // compare against original animCurve
                                KeysTest(animCurvesOriginal[id], animCurveImported, curveBinding.propertyName, keyComparer);
                            }
                            else
                            {
                                // compare by sampled keyvalues against original keydata
                                KeyValuesTest(keyData.keyTimes, keyData.GetAltKeyValues(id), animCurveImported, curveBinding.propertyName, isRotation);
                            }
                        }
                        else
                        {
                            // compare by sampled keyvalues against original animCurve
                            KeyValuesTest(animCurvesOriginal[id], animCurveImported, curveBinding.propertyName, isRotation);
                        }
                        result++;
                    }
                }

                return(result);
            }