using System; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace UnityEditor.Rendering { static class ContextualMenuDispatcher { [MenuItem("CONTEXT/Camera/Remove Component")] static void RemoveCameraComponent(MenuCommand command) { Camera camera = command.context as Camera; string error; if (!DispatchRemoveComponent(camera)) { //preserve built-in behavior if (CanRemoveComponent(camera, out error)) Undo.DestroyObjectImmediate(command.context); else EditorUtility.DisplayDialog("Can't remove component", error, "Ok"); } } static bool DispatchRemoveComponent(T component) where T : Component { Type type = RenderPipelineEditorUtility.FetchFirstCompatibleTypeUsingScriptableRenderPipelineExtension>(); if (type != null) { IRemoveAdditionalDataContextualMenu instance = (IRemoveAdditionalDataContextualMenu)Activator.CreateInstance(type); instance.RemoveComponent(component, ComponentDependencies(component)); return true; } return false; } static IEnumerable ComponentDependencies(Component component) => component.gameObject .GetComponents() .Where(c => c != component && c.GetType() .GetCustomAttributes(typeof(RequireComponent), true) .Count(att => att is RequireComponent rc && (rc.m_Type0 == component.GetType() || rc.m_Type1 == component.GetType() || rc.m_Type2 == component.GetType())) > 0); static bool CanRemoveComponent(Component component, out string error) { var dependencies = ComponentDependencies(component); if (dependencies.Count() == 0) { error = null; return true; } Component firstDependency = dependencies.First(); error = $"Can't remove {component.GetType().Name} because {firstDependency.GetType().Name} depends on it."; return false; } } /// /// Interface that should be used with [ScriptableRenderPipelineExtension(type))] attribute to dispatch ContextualMenu calls on the different SRPs /// /// This must be a component that require AdditionalData in your SRP public interface IRemoveAdditionalDataContextualMenu where T : Component { /// /// Remove the given component /// /// The component to remove /// Dependencies. void RemoveComponent(T component, IEnumerable dependencies); } }