public void registerMaterial(Material mat)
 {
     materials.getId(mat, true, (newMat) => {
         JsonMaterial.registerLinkedData(newMat, this);
         return;
     });
 }
        /*
         * Essentually the whole unity scene is a resource graph.
         * There are two resource types - "leaf" resources and "node" resources.
         * Leafs are only referenced by something, while nodes can reference leafs and other nodes via Ids....
         *
         * Well, the problem is we don't know how deep the rabbit hole goes, and one referenced resource can pull in other referenced
         * resources and so on. Given that a project can be huge, loading everything into memory at once might be unwise.
         *
         * As a result exporter will have to loop through the resources multiple times to acomodate for resoruces that were
         * possibly introduced. Henc the ugly "saveResourcesToPath" call with many many parameters.
         *
         * Originally I tried to avoid that by forcing specific order of initialziation which would eradicat possibility of
         * missing resources, but then I got prefabs and animator contorllers...
         */
        public JsonExternResourceList saveResourceToFolder(string baseDir, bool showGui, List <JsonScene> scenes, Logger logger, bool collectExternAssets)
        {
            Logger.makeValid(ref logger);
            var result = new JsonExternResourceList(collectExternAssets);

            //int lastSceneCount = 0;
            ///var sceneWatcher = scenes.createWatcher.... Nope!
            var sceneWatcher          = scenes.createWatcher();
            var terrainWatcher        = terrains.createWatcher();
            var meshWatcher           = meshRegistry.createWatcher();  //meshes.createWatcher();
            var materialsWatcher      = materials.createWatcher();
            var texWatcher            = textures.createWatcher();
            var cubemapWatcher        = cubemaps.createWatcher();
            var audioClipWatcher      = audioClips.createWatcher();
            var skeletonWatcher       = skelRegistry.createWatcher();
            var prefabWatcher         = prefabs.createWatcher();
            var animControllerWatcher = animatorControllers.createWatcher();
            var animClipWatcher       = animationClips.createWatcher();

            //processObjects = false;

            /* processObjects |= */

            /*
             *      saveResourcesToPath(result.scenes, ref lastSceneCount, baseDir, scenes,
             *      (objData, i) => objData, (obj) => obj.name, "scene", showGui);//Hmm. This one is not a resource mapper object...*/

            bool processObjects = true;

            while (processObjects)
            {
                /*
                 * Here we go, finally.
                 *
                 * This loop is meant to accomodate extensive and interconnected resource graph used by unity.
                 *
                 * Basically, during consturction of one or more JsonObjects, those objects may pull reference to something else that must
                 * ALSO be converted to some sort of json object.
                 *
                 * At this point a new resource reference (ResId) is created, and it has to be exported.
                 * Except... it is possible that the new resource has been pulled at the moment where this particular resource type
                 * has already been saved.
                 *
                 * Hence there's a resource watcher class which will monitor relevant resource registry for new IDs being added.
                 * As long as new ids are being generated, resource loop will continue, once they're no longer added, this is it.
                 *
                 * No more work to do, and the loop terminates.
                 */
                processObjects = false;

                processObjects |= saveResourcesToPath(result.scenes, baseDir, sceneWatcher,
                                                      (objData) => objData, (obj) => obj.name, "scene", showGui);
                processObjects |= saveResourcesToPath(result.terrains, baseDir, terrainWatcher,
                                                      (objData) => new JsonTerrainData(objData, this), (obj) => obj.name, "terrainData", showGui,
                                                      (asset) => result.registerAsset(asset)
                                                      );
                processObjects |= saveResourcesToPath(result.meshes, baseDir, meshWatcher,
                                                      (meshKey, idx, id) => makeJsonMesh(meshKey, id), (obj) => obj.name, "mesh", showGui);
                processObjects |= saveResourcesToPath(result.materials, baseDir, materialsWatcher,
                                                      (objData) => {
                    var mat = new JsonMaterial(objData, this);
                    if (!mat.supportedShader)
                    {
                        logger.logWarningFormat("Possibly unsupported shader \"{0}\" in material \"{1}\"(#{2}, path \"{3}\"). " +
                                                "Correct information transfer is not guaranteed.",
                                                mat.shader, mat.name, mat.id, mat.path);
                    }
                    return(mat);
                }, (obj) => obj.name, "material", showGui);

                processObjects |= saveResourcesToPath(result.textures, baseDir, texWatcher,
                                                      (objData) => new JsonTexture(objData, this), (obj) => obj.name, "texture", showGui,
                                                      (asset) => result.registerAsset(asset)
                                                      );

                processObjects |= saveResourcesToPath(result.cubemaps, baseDir, cubemapWatcher,
                                                      (objData) => new JsonCubemap(objData, this), (obj) => obj.name, "cubemap", showGui,
                                                      (asset) => result.registerAsset(asset)
                                                      );

                processObjects |= saveResourcesToPath(result.audioClips, baseDir, audioClipWatcher,
                                                      (objData) => new JsonAudioClip(objData, this), (obj) => obj.name, "audioClip", showGui);

                //skeletons are already sorted by id
                processObjects |= saveResourcesToPath(result.skeletons, baseDir,
                                                      skeletonWatcher,
                                                      (objData) => objData, (obj) => obj.name, "skeleton", showGui);

                processObjects |= saveResourcesToPath(
                    result.prefabs, baseDir, prefabWatcher,
                    (objData) => new JsonPrefabData(objData, this),
                    (obj) => obj.name,
                    "prefab", showGui);

                processObjects |= saveResourcesToPath(result.animatorControllers,
                                                      baseDir, animControllerWatcher,
                                                      (objData, idx, id) => new JsonAnimatorController(objData.controller, objData.animator, id, this),
                                                      (obj) => obj.name, "animatorController", showGui);

                processObjects |= saveResourcesToPath(result.animationClips,
                                                      baseDir, animClipWatcher,
                                                      (objData, idx, id) => new JsonAnimationClip(objData.animClip, objData.animator, id, this),
                                                      (obj) => obj.name, "animationClip", showGui);
            }

            result.resources = new List <string>(resources);
            result.resources.Sort();

            return(result);
        }