123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using FlatKit;
- using JetBrains.Annotations;
- using UnityEditor;
- using UnityEngine;
- using UnityEngine.Rendering;
- using UnityEngine.Rendering.Universal;
- public static class ObjectOutlineEditorUtils {
- private static readonly GUIStyle RichHelpBoxStyle = new(EditorStyles.helpBox) { richText = true };
- public static void SetActive(Material material, bool active) {
- var renderer = GetRenderer(Camera.current ?? Camera.main);
- if (renderer == null) {
- const string m = "<b>ScriptableRendererData</b> is required to enable per-object outlines.\n" +
- "Please assign a <b>URP Asset</b> in the Graphics settings.";
- EditorGUILayout.LabelField(m, RichHelpBoxStyle);
- return;
- }
- var features = GetRendererFeatures(renderer);
- if (features == null) {
- const string m = "<b>ScriptableRendererFeature</b> is required to enable per-object outlines.\n" +
- "Please assign a <b>URP Asset</b> in the Graphics settings.";
- EditorGUILayout.LabelField(m, RichHelpBoxStyle);
- return;
- }
- var feature = features.FirstOrDefault(f => f.GetType() == typeof(ObjectOutlineRendererFeature));
- if (feature == null) {
- if (active) {
- // Add the feature.
- var rendererData = GetRendererData();
- if (rendererData == null) return;
- feature = ScriptableObject.CreateInstance<ObjectOutlineRendererFeature>();
- feature.name = "Flat Kit Per Object Outline";
- AddRendererFeature(rendererData, feature);
- var m = $"<color=grey>[Flat Kit]</color> <b>Added</b> <color=green>{feature.name}</color> Renderer " +
- $"Feature to <b>{rendererData.name}</b>.";
- Debug.Log(m, rendererData);
- } else {
- // Feature not added and outline is disabled.
- return;
- }
- }
- // Register the material. This handles the feature activation.
- var outlineFeature = feature as ObjectOutlineRendererFeature;
- if (outlineFeature == null) {
- Debug.LogError("ObjectOutlineRendererFeature not found");
- return;
- }
- var featureIsUsed = outlineFeature.RegisterMaterial(material, active);
- // Remove the feature if no materials are using it.
- if (!featureIsUsed) {
- var rendererData = GetRendererData();
- if (rendererData == null) return;
- RemoveRendererFeature(rendererData, feature);
- var m = $"<color=grey>[Flat Kit]</color> <b>Removed</b> <color=green>{feature.name}</color> Renderer " +
- $"Feature from <b>{rendererData.name}</b> because no materials are using it.";
- Debug.Log(m, rendererData);
- }
- }
- private static void AddRendererFeature(ScriptableRendererData rendererData, ScriptableRendererFeature feature) {
- // Save the asset as a sub-asset.
- AssetDatabase.AddObjectToAsset(feature, rendererData);
- rendererData.rendererFeatures.Add(feature);
- rendererData.SetDirty();
- AssetDatabase.SaveAssets();
- AssetDatabase.Refresh();
- }
- private static void RemoveRendererFeature(ScriptableRendererData rendererData, ScriptableRendererFeature feature) {
- rendererData.rendererFeatures.Remove(feature);
- rendererData.SetDirty();
- // Remove the asset.
- AssetDatabase.RemoveObjectFromAsset(feature);
- AssetDatabase.SaveAssets();
- AssetDatabase.Refresh();
- }
- [CanBeNull]
- private static ScriptableRenderer GetRenderer(Camera camera) {
- if (!camera) {
- return null;
- }
- var additionalCameraData = camera.GetComponent<UniversalAdditionalCameraData>();
- if (!additionalCameraData) {
- return null;
- }
- var renderer = additionalCameraData.scriptableRenderer;
- return renderer;
- }
- private static List<ScriptableRendererFeature> GetRendererFeatures(ScriptableRenderer renderer) {
- var property =
- typeof(ScriptableRenderer).GetProperty("rendererFeatures", BindingFlags.NonPublic | BindingFlags.Instance);
- if (property == null) return null;
- var features = property.GetValue(renderer) as List<ScriptableRendererFeature>;
- return features;
- }
- internal static ScriptableRendererData GetRendererData() {
- #if UNITY_6000_0_OR_NEWER
- var srpAsset = GraphicsSettings.defaultRenderPipeline;
- #else
- var srpAsset = GraphicsSettings.renderPipelineAsset;
- #endif
- if (srpAsset == null) {
- const string m = "<b>Flat Kit</b> No SRP asset found. Please assign a URP Asset in the Graphics settings " +
- "to enable per-object outlines.";
- Debug.LogError(m);
- return null;
- }
- var field = typeof(UniversalRenderPipelineAsset).GetField("m_RendererDataList",
- BindingFlags.NonPublic | BindingFlags.Instance);
- var rendererDataList = (ScriptableRendererData[])field!.GetValue(srpAsset);
- var rendererData = rendererDataList.FirstOrDefault();
- if (rendererData == null) {
- Debug.LogError("No ScriptableRendererData found");
- return null;
- }
- return rendererData;
- }
- }
|