#if UNITY_EDITOR using System.IO; using System.Reflection; using UnityEditor; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; [InitializeOnLoad] public static class UIBlurBehindInstaller { private const string RendererDataPath = "Assets/Settings/Renderer2D.asset"; private const string MaterialFolderPath = "Assets/Materials"; private const string UIMaterialFolderPath = "Assets/Materials/UI"; private const string MaterialPath = "Assets/Materials/UI/Bansonic_UIBlurBehind.mat"; private const string ShaderName = "UI/Bansonic/Blur Behind"; private static bool installScheduled; static UIBlurBehindInstaller() { ScheduleInstall(); } [MenuItem("Bansonic/Rendering/Install UI Blur Behind")] public static void EnsureInstalledMenu() { EnsureInstalled(); } private static void ScheduleInstall() { if (installScheduled) { return; } installScheduled = true; EditorApplication.delayCall += RunScheduledInstall; } private static void RunScheduledInstall() { installScheduled = false; EnsureInstalled(); } private static void EnsureInstalled() { if (EditorApplication.isCompiling || BuildPipeline.isBuildingPlayer) { ScheduleInstall(); return; } if (!EnsureRendererFeatureInstalled()) { ScheduleInstall(); return; } if (!EnsureMaterialAsset()) { ScheduleInstall(); } } private static bool EnsureRendererFeatureInstalled() { ScriptableRendererData rendererData = AssetDatabase.LoadAssetAtPath(RendererDataPath); if (rendererData == null) { return false; } if (!rendererData.TryGetRendererFeature(out UIBlurBehindRendererFeature feature)) { feature = ScriptableObject.CreateInstance(); feature.name = "UI Blur Behind Renderer Feature"; feature.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing; feature.captureDownsample = 2; AssetDatabase.AddObjectToAsset(feature, rendererData); rendererData.rendererFeatures.Add(feature); rendererData.SetDirty(); EditorUtility.SetDirty(feature); EditorUtility.SetDirty(rendererData); TryValidateRendererFeatures(rendererData); AssetDatabase.SaveAssets(); AssetDatabase.ImportAsset(RendererDataPath); return true; } bool changed = false; if (feature.renderPassEvent != RenderPassEvent.AfterRenderingPostProcessing) { feature.renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing; changed = true; } if (feature.captureDownsample != 2) { feature.captureDownsample = 2; changed = true; } if (changed) { rendererData.SetDirty(); EditorUtility.SetDirty(feature); EditorUtility.SetDirty(rendererData); AssetDatabase.SaveAssets(); } return true; } private static bool EnsureMaterialAsset() { Shader shader = Shader.Find(ShaderName); if (shader == null) { return false; } EnsureFolder("Assets", "Materials"); EnsureFolder(MaterialFolderPath, "UI"); Material material = AssetDatabase.LoadAssetAtPath(MaterialPath); if (material == null) { material = new Material(shader); material.name = "Bansonic_UIBlurBehind"; material.SetFloat("_BlurRadius", 0.95f); material.SetFloat("_BlurSpread", 0.28f); material.SetFloat("_BackgroundOpacity", 1.0f); material.SetFloat("_TintStrength", 0.0f); AssetDatabase.CreateAsset(material, MaterialPath); AssetDatabase.SaveAssets(); return true; } bool changed = false; if (material.shader != shader) { material.shader = shader; changed = true; } if (changed) { EditorUtility.SetDirty(material); AssetDatabase.SaveAssets(); } return true; } private static void EnsureFolder(string parentPath, string folderName) { string combined = Path.Combine(parentPath, folderName).Replace("\\", "/"); if (AssetDatabase.IsValidFolder(combined)) { return; } AssetDatabase.CreateFolder(parentPath, folderName); } private static void TryValidateRendererFeatures(ScriptableRendererData rendererData) { MethodInfo validateMethod = typeof(ScriptableRendererData).GetMethod("ValidateRendererFeatures", BindingFlags.Instance | BindingFlags.NonPublic); validateMethod?.Invoke(rendererData, null); } } #endif