// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; namespace Microsoft.MixedReality.GraphicsTools.Editor { /// /// An abstract editor component to improve the editor experience with ClippingPrimitives. /// [CustomEditor(typeof(ClippingPrimitive))] [CanEditMultipleObjects] public abstract class ClippingPrimitiveEditor : UnityEditor.Editor { /// /// Notifies the Unity editor if this object has custom frame bounds. /// /// True if custom frame bounds can be used from OnGetFrameBounds. protected abstract bool HasFrameBounds(); /// /// Returns the bounds the editor should focus on. /// /// The bounds of the clipping primitive. protected abstract Bounds OnGetFrameBounds(); private ClippingPrimitive clippingPrimitive; private SerializedProperty m_Script; private SerializedProperty applyToSharedMaterial; private void OnEnable() { clippingPrimitive = (ClippingPrimitive)target; m_Script = serializedObject.FindProperty(nameof(m_Script)); applyToSharedMaterial = serializedObject.FindProperty(nameof(applyToSharedMaterial)); } /// /// Looks for changes to the list of renderers and materials and gracefully adds and removes them. /// public override void OnInspectorGUI() { var previousRenderers = clippingPrimitive.GetRenderersCopy(); var previousMaterials = clippingPrimitive.GetMaterialsCopy(); using (var check = new EditorGUI.ChangeCheckScope()) { InspectorUtilities.DrawReadonlyPropertyField(m_Script); if (HasNoRenderers(previousRenderers)) { EditorGUILayout.PropertyField(applyToSharedMaterial); } else { InspectorUtilities.DrawReadonlyPropertyField(applyToSharedMaterial); } DrawPropertiesExcluding(serializedObject, nameof(m_Script), nameof(applyToSharedMaterial)); if (check.changed) { // Flagging changes other than renderers clippingPrimitive.IsDirty = true; serializedObject.ApplyModifiedProperties(); } } // Add or remove and renderers that were added or removed via the inspector. var currentRenderers = clippingPrimitive.GetRenderersCopy(); foreach (var renderer in previousRenderers.Except(currentRenderers)) { // ResetRenderer rather than RemoveRenderer since the renderer has already been removed from the list. clippingPrimitive.ResetRenderer(renderer); } foreach (var renderer in currentRenderers.Except(previousRenderers)) { clippingPrimitive.AddRenderer(renderer); } // Add or remove and materials that were added or removed via the inspector. var currentMaterials = clippingPrimitive.GetMaterialsCopy(); foreach (var material in previousMaterials.Except(currentMaterials)) { // ResetMaterial rather than RemoveMaterial since the material has already been removed from the list. clippingPrimitive.ResetMaterial(material); } foreach (var material in currentMaterials.Except(previousMaterials)) { clippingPrimitive.AddMaterial(material); } } private static bool HasNoRenderers(IEnumerable renderers) { foreach (var renderer in renderers) { if (renderer != null) { return false; } } return true; } } }