using System.Collections; using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine; namespace SLZ.URPModResources { /// /// Extracts assets from hidden folders inside the URP package into the project. Made as a replacement for Unity's sample system /// that we were using before to address the issue that unity installs the assets to a path relative to the package version number. /// Shader includes rely on absolute paths, so the sample system is unsuitable for this usecase. Also the samples are buried in /// Unity's package manager so most users won't even know they exist. /// public static class ExtractAssets { #if !MARROW_PROJECT static string pkgPathShader = "Packages/com.unity.render-pipelines.universal/ModResources/SLZShaders~/"; static string pkgPathAmplify = "Packages/com.unity.render-pipelines.universal/ModResources/AmplifyExtensions~/"; static string assetPathShader = "Assets/SLZShaders/"; static string assetPathAmplify = "Assets/AmplifyShaderEditor/"; /// /// Extract the bonelab shader files into the assets folder. /// /// Do we delete all files in the project with the same GUID's those in this package? GUIDs come from .GUIDList.txt in the package folder internal static void ExtractShaders(bool cleanInstall) { string projectPath = Path.GetDirectoryName(Application.dataPath); string packagePath = Path.Combine(projectPath, pkgPathShader); string assetsPath = Path.Combine(projectPath, assetPathShader); if (cleanInstall) { string GUIDListPath = packagePath + ".GUIDList.txt"; if (File.Exists(GUIDListPath)) { NukeOldFiles(GUIDListPath); } else { Debug.LogWarning("Missing GUID list, will not attempt to delete old versions of files. GUIDs may get mangled if imported assets have same GUIDs as other assets in the project!"); } } CopyDirectory(packagePath, assetsPath); AssetDatabase.Refresh(); } internal static void ExtractAmplify(bool cleanInstall) { string projectPath = Path.GetDirectoryName(Application.dataPath); string packagePath = Path.Combine(projectPath, pkgPathAmplify); string assetsPath = Path.Combine(projectPath, assetPathAmplify); string GUIDListPath = packagePath + ".GUIDList.txt"; if (cleanInstall) { if (File.Exists(GUIDListPath)) { NukeOldFiles(GUIDListPath); } else { Debug.LogWarning("Missing GUID list, will not attempt to delete old versions of files. GUIDs may get mangled if imported assets have same GUIDs as other assets in the project!"); } } CopyDirectory(packagePath, assetsPath); AssetDatabase.Refresh(); } static void NukeOldFiles(string GUIDListPath) { string projectPath = Path.GetDirectoryName(Application.dataPath); List deletePaths = new List(); using (StreamReader sr = new StreamReader(GUIDListPath)) { string guid; while ((guid = sr.ReadLine()) != null && guid.Length >= 32) { guid = guid.Substring(0, 32); string assetPath = AssetDatabase.GUIDToAssetPath(guid); if (!string.IsNullOrEmpty(assetPath) && File.Exists(Path.Combine(projectPath, assetPath)) && !assetPath.StartsWith("Packages")) { deletePaths.Add(assetPath); //AssetDatabase.DeleteAsset(assetPath); //File.Delete(Path.Combine(projectPath, assetPath)); //File.Delete(Path.Combine(projectPath, assetPath + ".meta")); } } } List failedPaths = new List(); AssetDatabase.DeleteAssets(deletePaths.ToArray(), failedPaths); } /// /// Copied from Microsoft docs (https://learn.microsoft.com/en-us/dotnet/standard/io/how-to-copy-directories), kinda silly that System.IO has no method for copying a folder. /// /// Directory to copy from /// Directory to copy to /// static void CopyDirectory(string sourceDir, string destinationDir) { // Get information about the source directory var dir = new DirectoryInfo(sourceDir); // Check if the source directory exists if (!dir.Exists) throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}"); // Cache directories before we start copying DirectoryInfo[] dirs = dir.GetDirectories(); // Create the destination directory Directory.CreateDirectory(destinationDir); // Get the files in the source directory and copy to the destination directory foreach (FileInfo file in dir.GetFiles()) { string targetFilePath = Path.Combine(destinationDir, file.Name); file.CopyTo(targetFilePath, true); } foreach (DirectoryInfo subDir in dirs) { string newDestinationDir = Path.Combine(destinationDir, subDir.Name); CopyDirectory(subDir.FullName, newDestinationDir); } } #endif } }