public Sprite GetSprite(string spriteName) { var spriteAssetPath = Path.Combine(spriteOutputFolderAssetPath, spriteName) + ".png"; // 相対パスの記述に対応した // var fileInfo = new FileInfo(path); なぜフルパスにしたか忘れた spriteAssetPath = TextureUtil.GetSameImagePath(spriteAssetPath); var sprite = AssetDatabase.LoadAssetAtPath <Sprite>(spriteAssetPath); if (sprite == null) { Debug.LogWarning($"pngで見つからなかった{spriteAssetPath}"); sprite = AssetDatabase.LoadAssetAtPath <Sprite>(Path.ChangeExtension(spriteAssetPath, "asset")); } if (sprite == null) { var folderPath = Path.GetDirectoryName(spriteAssetPath); var obj = AssetDatabase.LoadAssetAtPath <Object>(folderPath); Debug.LogError($"[{Importer.NAME}] sprite not found:\"{spriteAssetPath}\"", obj); } return(sprite); }
/// <summary> /// Assetディレクトリに追加されたファイルを確認、インポート処理を行う /// </summary> /// <param name="importedAssetPaths"></param> /// <param name="optionOverwriteImport"></param> /// <param name="optionDeleteImportedAssets"></param> private static async Task <int> Import(string baseFolderPath, IEnumerable <string> importedAssetPaths, bool optionOverwriteImport, bool optionDeleteImportedAssets) { var importedPaths = importedAssetPaths.ToList(); _progressTotal = importedPaths.Count(); if (_progressTotal == 0) { return(0); } _progressCount = 0; // Png->Spriteに変換するリストをクリアする PreprocessTexture.SlicedTextures = null; // インポートされたファイルからフォルダパスリストを作成する // Key: AssetPath // Value: ディレクトリにあるファイルの拡張子 var importedFolderAssetPaths = new FolderInfos(); foreach (var importedAssetPath in importedAssetPaths) { if (EditorUtil.IsFolder(importedAssetPath) == true) { // すでにフォルダパスはスルー continue; } var folderPath = Path.GetDirectoryName(importedAssetPath); var extension = Path.GetExtension(importedAssetPath); importedFolderAssetPaths.Add(folderPath, extension); } // 出力フォルダの作成 foreach (var importedFolderInfo in importedFolderAssetPaths) { if (EditorUtil.IsFolder(importedFolderInfo.Key) != true) { continue; } // フォルダであった場合 var importedFullPath = Path.GetFullPath(importedFolderInfo.Key); var subFolderName = EditorUtil.GetSubFolderName(baseFolderPath, importedFolderInfo.Key + "/file.tmp"); // このフォルダには.pngファイルがあるか var isSpriteFolder = importedFolderInfo.Value.Contains(".png"); // スプライト出力フォルダの準備 if (isSpriteFolder) { var outputSpritesFolderAssetPath = Path.Combine( EditorUtil.GetOutputSpritesFolderAssetPath(), subFolderName); if (Directory.Exists(outputSpritesFolderAssetPath)) { // フォルダがすでにある インポートファイルと比較して、出力先にある必要のないファイルを削除する // ダブっている分は比較し、異なっている場合に上書きするようにする var outputFolderInfo = new DirectoryInfo(outputSpritesFolderAssetPath); var importFolderInfo = new DirectoryInfo(importedFullPath); var existSpritePaths = outputFolderInfo.GetFiles("*.png", SearchOption.AllDirectories); var importSpritePaths = importFolderInfo.GetFiles("*.png", SearchOption.AllDirectories); // outputフォルダにある importにはないファイルをリストアップする // そしてそれを削除するという処理であったが不具合が発生する // 別のLayout.Jsonから参照されているテクスチャも消えてしまう // テクスチャについて未使用を削除するには // - フォルダを消して再インポート // - imageHashMapキャッシュファイルからつかわれていないものを削除する という処理をいれなければならない // var deleteEntries = existSpritePaths.Except(importSpritePaths, new FileInfoComparer()).ToList(); var deleteEntries = new List <FileInfo>(); // スプライト出力フォルダがすでにある場合はTextureハッシュキャッシュを削除する deleteEntries.Add(new FileInfo(outputSpritesFolderAssetPath + "/" + TextureUtil.ImageHashMapCacheFileName)); deleteEntries.Add(new FileInfo(outputSpritesFolderAssetPath + "/" + TextureUtil.ImagePathMapCacheFileName)); if (!optionOverwriteImport) { // 削除する foreach (var fileInfo in deleteEntries) { AssetDatabase.DeleteAsset(EditorUtil.ToAssetPath(fileInfo.FullName)); } } } else { // Debug.Log($"[{Importer.Name}] Create Folder: {subFolderName}"); EditorUtil.CreateFolder(outputSpritesFolderAssetPath); } } var outputPrefabsFolderAssetPath = Path.Combine(EditorUtil.GetOutputPrefabsFolderAssetPath(), subFolderName); if (!Directory.Exists(outputPrefabsFolderAssetPath)) { EditorUtil.CreateFolder(outputPrefabsFolderAssetPath); } UpdateDisplayProgressBar($"Import Folder Preparation: {subFolderName}"); } await Task.Delay(1000); // ディレクトリが作成されたり、画像が削除されるためRefresh AssetDatabase.Refresh(); // フォルダが作成され、そこに画像を出力する場合 // Refresh後、DelayCallで画像生成することで、処理が安定した // await Task.Delay(1000); // SpriteイメージのハッシュMapをクリアしたかどうかのフラグ // importedAssetsに一気に全部の新規ファイルが入ってくる前提の処理 // 全スライス処理が走る前、最初にClearImageMapをする var clearedImageMap = false; // 画像コンバート スライス処理 var messageCounter = new Dictionary <string, int>(); var total = 0; try { foreach (var pngAssetPath in importedPaths) { // Debug.Log($"Slice: {importedAsset}"); if (!pngAssetPath.EndsWith(".png", StringComparison.Ordinal)) { continue; } // if (!clearedImageMap) { clearedImageMap = true; } var subFolderName = EditorUtil.GetSubFolderName(baseFolderPath, pngAssetPath); var outputFolderPath = Path.Combine(EditorUtil.GetOutputSpritesFolderAssetPath(), subFolderName); var outputFilePath = Path.Combine(outputFolderPath, Path.GetFileName(pngAssetPath)); // スライス処理 var message = TextureUtil.SliceSprite(outputFilePath, pngAssetPath); total++; _progressCount += 2; // pngファイル と png.jsonファイル UpdateDisplayProgressBar(message); // 出力されたログをカウントする if (messageCounter.ContainsKey(message)) { messageCounter[message] = messageCounter[message] + 1; } else { messageCounter.Add(message, 1); } } } catch (Exception ex) { Debug.LogAssertion(ex.Message); Debug.LogAssertion(ex.StackTrace); } foreach (var keyValuePair in messageCounter) { Debug.Log($"[{Importer.NAME}] {keyValuePair.Key} {keyValuePair.Value}/{total}"); } var importLayoutFilePaths = new List <string>(); foreach (var layoutFilePath in importedPaths) { if (!layoutFilePath.EndsWith(".layout.json", StringComparison.OrdinalIgnoreCase)) { continue; } importLayoutFilePaths.Add(layoutFilePath); } string GetPrefabPath(string layoutFilePath) { var prefabFileName = Path.GetFileName(layoutFilePath).Replace(".layout.json", "") + ".prefab"; var subFolderName = EditorUtil.GetSubFolderName(baseFolderPath, layoutFilePath); var saveAssetPath = Path.Combine(Path.Combine(EditorUtil.GetOutputPrefabsFolderAssetPath(), subFolderName), prefabFileName); return(saveAssetPath); } string GetPrefabName(string layoutFilePath) { var prefabFileName = Path.GetFileName(layoutFilePath).Replace(".layout.json", ""); var subFolderName = EditorUtil.GetSubFolderName(baseFolderPath, layoutFilePath); return(subFolderName + "/" + prefabFileName); } // 出力されたスライスPNGをSpriteに変換する処理を走らせるために必須 // ここでPreprocessTextureが実行されなければいけない AssetDatabase.Refresh(); await Task.Delay(1000); if (PreprocessTexture.SlicedTextures != null && PreprocessTexture.SlicedTextures.Count != 0) { // Debug.LogWarning($"[{Importer.Name}] SlicedTextures is still available."); } var prefabs = new List <GameObject>(); // .layout.jsonを全て読み込んで、コンバート順をソートする // Item1: prefab name dependensyチェック用 // Item2: file path // Item3: json data var layoutJsons = new List <Tuple <string, string, Dictionary <string, object> > >(); foreach (var layoutFilePath in importLayoutFilePaths) { var prefabName = GetPrefabName(layoutFilePath); // Load JSON var jsonText = File.ReadAllText(layoutFilePath); var json = Json.Deserialize(jsonText) as Dictionary <string, object>; layoutJsons.Add( new Tuple <string, string, Dictionary <string, object> >(prefabName, layoutFilePath, json)); } // コンバートする順番を決める layoutJsons.Sort((a, b) => { List <object> GetDependency(Dictionary <string, object> json) { return(json.GetDic("info")?.GetArray("dependency")); } int GetDependencyCount(Dictionary <string, object> json) { var dr = GetDependency(json); return(dr?.Count ?? 0); } bool Check(string name, Dictionary <string, object> json) { var nameList = GetDependency(json); if (nameList == null) { return(false); } return(nameList.Any(o => name == o as string)); } // aはbより先に処理すべきか if (Check(a.Item1, b.Item3)) { return(-1); } // bはaより先に処理すべきか if (Check(b.Item1, a.Item3)) { return(1); } // 依存ファイル数で決着をつける return(GetDependencyCount(a.Item3) - GetDependencyCount(b.Item3)); }); // Create Prefab foreach (var layoutJson in layoutJsons) { UpdateDisplayProgressBar($"Layout: {layoutJson.Item1}"); _progressCount += 1; var layoutFilePath = layoutJson.Item2; var subFolderName = EditorUtil.GetSubFolderName(baseFolderPath, layoutFilePath); GameObject go = null; try { // Debug.Log($"[{Importer.Name}] in process...{Path.GetFileName(layoutFilePath)}"); var saveAssetPath = GetPrefabPath(layoutFilePath); var spriteOutputFolderAssetPath = Path.Combine(EditorUtil.GetOutputSpritesFolderAssetPath(), subFolderName); var fontAssetPath = EditorUtil.GetFontsFolderAssetPath(); // overwriteImportFlagがTrueなら、ベースとなるPrefab上に生成していく // 利用できるオブジェクトは利用していく if (optionOverwriteImport) { // すでにあるプレハブを読み込む var prefab = AssetDatabase.LoadAssetAtPath <GameObject>(saveAssetPath); if (prefab != null) { go = PrefabUtility.InstantiatePrefab(prefab) as GameObject; PrefabUtility.UnpackPrefabInstance(go, PrefabUnpackMode.OutermostRoot, InteractionMode.AutomatedAction); } } // Render Context var renderContext = new RenderContext(spriteOutputFolderAssetPath, fontAssetPath, go); if (optionOverwriteImport) { renderContext.OptionAddXdGuidComponent = true; } // Load JSON var jsonText = File.ReadAllText(layoutFilePath); var json = Json.Deserialize(jsonText) as Dictionary <string, object>; //var info = json.GetDic("info"); //Validation(info); var rootJson = json.GetDic("root"); // Create Prefab var prefabCreator = new PrefabCreator(prefabs); prefabCreator.Create(ref go, renderContext, rootJson); // Save Prefab EditorUtil.CreateFolder(Path.GetDirectoryName(saveAssetPath)); var savedAsset = PrefabUtility.SaveAsPrefabAsset(go, saveAssetPath); Debug.Log($"[{Importer.NAME}] Created: <color=#7FD6FC>{Path.GetFileName(saveAssetPath)}</color>", savedAsset); } catch (Exception ex) { Debug.LogAssertion($"[{Importer.NAME}] " + ex.Message + "\n" + ex.StackTrace); // 変換中例外が起きた場合もテンポラリGameObjectを削除する EditorUtility.ClearProgressBar(); EditorUtility.DisplayDialog("Import Failed", ex.Message, "Close"); throw; } finally { Object.DestroyImmediate(go); } AssetDatabase.Refresh(); await Task.Delay(100); } // インポートしたファイルを削除し、そのフォルダが空になったらフォルダも削除する if (optionDeleteImportedAssets) { foreach (var forImportAssetPath in importedAssetPaths) { // フォルダの場合はスルー if (EditorUtil.IsFolder(forImportAssetPath) == true) { continue; } // インポートするファイルを削除 AssetDatabase.DeleteAsset(forImportAssetPath); // ファイルがあったフォルダが空になったかチェック var folderName = Path.GetDirectoryName(forImportAssetPath); var files = Directory.GetFiles(folderName); if (files.Length == 0) { // フォルダの削除 // Debug.Log($"ディレクトリ削除{folderName}"); AssetDatabase.DeleteAsset(folderName); } } } AssetDatabase.Refresh(); EditorUtility.ClearProgressBar(); return(0); }