#if UNITY_EDITOR using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEditor.AddressableAssets; using UnityEditor.AddressableAssets.Settings; using UnityEngine; namespace DDD { public static class AssetPostprocessorEnvironment { private static readonly HashSet SpriteTargetPaths = new(); private static readonly HashSet MeshTargetPaths = new(); private static readonly int BaseMap = Shader.PropertyToID("_BaseMap"); private static readonly int MetallicGlossMap = Shader.PropertyToID("_MetallicGlossMap"); private static readonly int BumpMap = Shader.PropertyToID("_BumpMap"); private static readonly int EmissionMap = Shader.PropertyToID("_EmissionMap"); private const string BaseMeshPrefabPath = "Assets/_DDD/_Raw/Environments/Env_Mesh_Prop.prefab"; private const string BaseSpritePrefabPath = "Assets/_DDD/_Raw/Environments/Env_Sprite_Background.prefab"; private const string ShaderName = "Universal Render Pipeline/LitEnvironment"; private const string Prop = "Prop_"; private const string BaseColorUpper = "_BASECOLOR"; private const string MohsUpper = "_MOHS"; private const string NormalUpper = "_NORMAL"; private const string EmissionUpper = "_EMISSION"; public static void OnPreprocessTexture(TextureImporter importer) { var path = importer.assetPath; string fileNameUpper = Utils.FileName(path).ToUpper(); if (fileNameUpper.Contains(NormalUpper)) { importer.textureType = TextureImporterType.NormalMap; } else { importer.textureType = TextureImporterType.Default; importer.sRGBTexture = true; } importer.mipmapEnabled = true; } public static void OnAdd(string path) { string upperPath = path.ToUpper(); if (upperPath.Contains(PathConstants.RawEnvSpritesPathUpper) && upperPath.Contains(ExtenstionConstants.PngExtensionUpper)) { if (!SpriteTargetPaths.Contains(path)) SpriteTargetPaths.Add(path); } else if (upperPath.Contains(PathConstants.RawEnvMeshesPathUpper) && upperPath.Contains(ExtenstionConstants.PngExtensionUpper)) { if (!MeshTargetPaths.Contains(path)) MeshTargetPaths.Add(path); } } public static void OnRemove(string path, string movePath = "") { string upperPath = path.ToUpper(); if (upperPath.Contains(PathConstants.RawEnvSpritesPathUpper) && upperPath.Contains(ExtenstionConstants.PngExtensionUpper)) { if (!SpriteTargetPaths.Contains(path)) SpriteTargetPaths.Add(path); } else if (upperPath.Contains(PathConstants.RawEnvMeshesPathUpper) && upperPath.Contains(ExtenstionConstants.PngExtensionUpper)) { if (!MeshTargetPaths.Contains(path)) MeshTargetPaths.Add(path); } } public static void BuildMaterialAndPrefab(string path, bool isMesh) { var di = new DirectoryInfo(path); if (!di.Exists) return; string folderName = di.Name; string rawRoot = PathConstants.RawFolderPath; // "/_Raw" string addrRoot = PathConstants.AddressablesFolderPath; // "/_Addressables" string destDir = path.Replace(rawRoot, addrRoot); string materialPath = $"{destDir}/{folderName}{ExtenstionConstants.MaterialExtenstionLower}"; string prefabPath = $"{destDir}/{Prop}{folderName}{ExtenstionConstants.PrefabExtenstionLower}"; Utils.MakeFolderFromFilePath(materialPath); // 머티리얼 생성 또는 로드 Material mat = AssetDatabase.LoadAssetAtPath(materialPath); if (mat == null) { mat = new Material(Shader.Find(ShaderName)); AssetDatabase.CreateAsset(mat, materialPath); } // PNG 텍스처 매핑 var files = Directory.GetFiles(path, $"*{ExtenstionConstants.PngExtensionLower}", SearchOption.TopDirectoryOnly); foreach (var file in files) { string texName = Path.GetFileNameWithoutExtension(file).ToUpper(); var tex = AssetDatabase.LoadAssetAtPath(file); if (tex == null) continue; if (texName.Contains(BaseColorUpper)) { mat.SetTexture(BaseMap, tex); } else if (texName.Contains(MohsUpper)) { mat.SetTexture(MetallicGlossMap, tex); } else if (texName.Contains(NormalUpper)) { mat.SetTexture(BumpMap, tex); } else if (texName.Contains(EmissionUpper)) { mat.SetTexture(EmissionMap, tex); } } AssetDatabase.ImportAsset(materialPath, ImportAssetOptions.ForceUpdate); AssetDatabase.SaveAssets(); CreateOrUpdatePrefabVariant(folderName, mat, prefabPath, isMesh); } private static void CreateOrUpdatePrefabVariant(string folderName, Material mat, string prefabPath, bool isMesh) { if (AssetDatabase.LoadAssetAtPath(prefabPath) != null) return; string basePrefabPath = isMesh ? BaseMeshPrefabPath : BaseSpritePrefabPath; var basePrefab = AssetDatabase.LoadAssetAtPath(basePrefabPath); if (basePrefab == null) { Debug.LogWarning($"Base prefab not found: {basePrefabPath}"); return; } GameObject instancePrefab = AssetDatabase.LoadAssetAtPath(prefabPath); if (instancePrefab == null) { instancePrefab = (GameObject)PrefabUtility.InstantiatePrefab(basePrefab); instancePrefab.name = $"{Prop}{folderName}"; } var renderer = instancePrefab.GetComponentInChildren(); if (renderer != null) renderer.sharedMaterial = mat; Utils.MakeFolderFromFilePath(prefabPath); PrefabUtility.SaveAsPrefabAssetAndConnect(instancePrefab, prefabPath, InteractionMode.AutomatedAction); Object.DestroyImmediate(instancePrefab); AssetDatabase.ImportAsset(prefabPath, ImportAssetOptions.ForceUpdate); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } public static void BuildTarget() { foreach (var path in SpriteTargetPaths) { BuildMaterialAndPrefab(Utils.FolderPath(path), isMesh: false); } foreach (var path in MeshTargetPaths) { BuildMaterialAndPrefab(Utils.FolderPath(path), isMesh: true); } SpriteTargetPaths.Clear(); MeshTargetPaths.Clear(); } } } #endif