public void TestExporterCallbacks()
        {
            var tree   = CreateHierarchy();
            var tester = new CallbackTester(tree.transform, GetRandomFbxFilePath());
            var n      = tree.GetComponentsInChildren <Transform>().Length;

            // No callbacks registered => no calls.
            tester.Verify(0, 0);

            ModelExporter.RegisterMeshObjectCallback(tester.CallbackForObject);
            ModelExporter.RegisterMeshCallback <FbxPrefab>(tester.CallbackForFbxPrefab);

            // No fbprefab => no component calls, but every object called.
            tester.Verify(0, n);

            // Add a fbxprefab, check every object called and the prefab called.
            tree.transform.Find("Parent1").gameObject.AddComponent <FbxPrefab>();
            tester.Verify(1, n);

            // Make the object report it's replacing everything => no component calls.
            tester.Verify(0, n, objectResult: true);

            // Make sure we can't register for a component twice, but we can
            // for an object.  Register twice for an object means two calls per
            // object.
            Assert.That(() => ModelExporter.RegisterMeshCallback <FbxPrefab>(tester.CallbackForFbxPrefab),
                        Throws.Exception);
            ModelExporter.RegisterMeshObjectCallback(tester.CallbackForObject);
            tester.Verify(1, 2 * n);

            // Register twice but return true => only one call per object.
            tester.Verify(0, n, objectResult: true);

            // Unregister once => only one call per object, and no more for the prefab.
            ModelExporter.UnRegisterMeshCallback <FbxPrefab>();
            ModelExporter.UnRegisterMeshObjectCallback(tester.CallbackForObject);
            tester.Verify(0, n);

            // Legal to unregister if already unregistered.
            ModelExporter.UnRegisterMeshCallback <FbxPrefab>();
            tester.Verify(0, n);

            // Register same callback twice gets back to original state.
            ModelExporter.UnRegisterMeshObjectCallback(tester.CallbackForObject);
            tester.Verify(0, 0);

            // Legal to unregister if already unregistered.
            ModelExporter.UnRegisterMeshObjectCallback(tester.CallbackForObject);
            tester.Verify(0, 0);

            ///////////////////////
            // Test that the callbacks not only get called, but can replace
            // meshes.
            var sphere     = GameObject.CreatePrimitive(PrimitiveType.Capsule);
            var sphereMesh = sphere.GetComponent <MeshFilter>().sharedMesh;
            var cube       = GameObject.CreatePrimitive(PrimitiveType.Cube);
            var cubeMesh   = cube.GetComponent <MeshFilter>().sharedMesh;

            // Pick on the fbxprefab to output a sphere in place of the cube.
            // the fbxprefab is on parent1.
            string     filename;
            GameObject asset;
            Mesh       assetMesh;

            GetMeshForComponent <FbxPrefab> prefabCallback =
                (ModelExporter exporter, FbxPrefab component, FbxNode node) => {
                exporter.ExportMesh(sphereMesh, node);
                return(true);
            };

            ModelExporter.RegisterMeshCallback(prefabCallback);
            filename = GetRandomFbxFilePath();
            ModelExporter.ExportObject(filename, tree);
            ModelExporter.UnRegisterMeshCallback <FbxPrefab>();

            asset     = AssetDatabase.LoadMainAssetAtPath(filename) as GameObject;
            assetMesh = asset.transform.Find("Parent1").GetComponent <MeshFilter>().sharedMesh;
            Assert.AreEqual(sphereMesh.triangles.Length, assetMesh.triangles.Length);
            assetMesh = asset.transform.Find("Parent2").GetComponent <MeshFilter>().sharedMesh;
            Assert.AreEqual(cubeMesh.triangles.Length, assetMesh.triangles.Length);

            // Try again, but this time pick on Parent2 by name (different just
            // to make sure we don't pass if the previous pass didn't
            // actually unregister).
            filename = GetRandomFbxFilePath();
            GetMeshForObject callback =
                (ModelExporter exporter, GameObject gameObject, FbxNode node) => {
                if (gameObject.name == "Parent2")
                {
                    exporter.ExportMesh(sphereMesh, node);
                    return(true);
                }
                else
                {
                    return(false);
                }
            };

            ModelExporter.RegisterMeshObjectCallback(callback);
            ModelExporter.ExportObject(filename, tree);
            ModelExporter.UnRegisterMeshObjectCallback(callback);

            asset     = AssetDatabase.LoadMainAssetAtPath(filename) as GameObject;
            assetMesh = asset.transform.Find("Parent1").GetComponent <MeshFilter>().sharedMesh;
            Assert.AreEqual(cubeMesh.triangles.Length, assetMesh.triangles.Length);
            assetMesh = asset.transform.Find("Parent2").GetComponent <MeshFilter>().sharedMesh;
            Assert.AreEqual(sphereMesh.triangles.Length, assetMesh.triangles.Length);
        }