From 04cca69f1981640547c09d63222411b149e772c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20V=C3=A1zquez?= Date: Thu, 21 Jan 2021 17:09:30 +0100 Subject: [PATCH 1/2] [HDRP]Improvements and fixes on Volumes Components Inspectors - https://fogbugz.unity3d.com/f/cases/1297795/ - https://fogbugz.unity3d.com/f/cases/1303477/ - https://fogbugz.unity3d.com/f/cases/1297789/ --- com.unity.render-pipelines.core/CHANGELOG.md | 5 +- .../Editor/Volume/VolumeComponentEditor.cs | 100 ++++++++++++++-- .../Runtime/Common/CoreAttributes.cs | 8 ++ .../Runtime/Volume/VolumeComponent.cs | 24 ++-- .../Tests/Editor/ReflectionUtils.cs | 79 +++++++++++++ .../Tests/Editor/ReflectionUtils.cs.meta | 11 ++ .../Tests/Editor/Volumes.meta | 8 ++ .../Editor/Volumes/VolumeComponentTests.cs | 109 ++++++++++++++++++ .../Volumes/VolumeComponentTests.cs.meta | 11 ++ .../Editor/PostProcessing/BloomEditor.cs | 2 - .../PostProcessing/DepthOfFieldEditor.cs | 2 - .../Editor/PostProcessing/ExposureEditor.cs | 2 - .../Editor/PostProcessing/MotionBlurEditor.cs | 2 - .../Sky/AtmosphericScattering/FogEditor.cs | 2 - .../CloudLayer/CloudLayerEditor.cs | 2 - .../Editor/Sky/HDRISky/HDRISkyEditor.cs | 1 - .../Lighting/AtmosphericScattering/Fog.cs | 11 ++ .../ScreenSpaceLighting/AmbientOcclusion.cs | 1 + .../PostProcessing/Components/Bloom.cs | 4 + .../PostProcessing/Components/DepthOfField.cs | 4 +- .../PostProcessing/Components/Exposure.cs | 3 + .../PostProcessing/Components/MotionBlur.cs | 6 + .../Sky/CloudSystem/CloudLayer/CloudLayer.cs | 3 + .../Runtime/Sky/HDRISky/HDRISky.cs | 13 +++ .../Tests/Editor/Volumes.meta | 8 ++ 25 files changed, 390 insertions(+), 31 deletions(-) create mode 100644 com.unity.render-pipelines.core/Tests/Editor/ReflectionUtils.cs create mode 100644 com.unity.render-pipelines.core/Tests/Editor/ReflectionUtils.cs.meta create mode 100644 com.unity.render-pipelines.core/Tests/Editor/Volumes.meta create mode 100644 com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentTests.cs create mode 100644 com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentTests.cs.meta create mode 100644 com.unity.render-pipelines.high-definition/Tests/Editor/Volumes.meta diff --git a/com.unity.render-pipelines.core/CHANGELOG.md b/com.unity.render-pipelines.core/CHANGELOG.md index 4eabb0a713c..549580962b2 100644 --- a/com.unity.render-pipelines.core/CHANGELOG.md +++ b/com.unity.render-pipelines.core/CHANGELOG.md @@ -16,7 +16,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed - Fixed the default background color for previews to use the original color. -- Fixed ACES tonemapping for Nintendo Switch by forcing some shader color conversion functions to full float precision. +- Fixed spacing between property fields on the Volume Component Editors. +- Fixed ALL/NONE to maintain the state on the Volume Component Editors. +- Fixed the selection of the Additional properties from ALL/NONE when the option "Show additional properties" is disabled +- Fixed ACES tonemaping for Nintendo Switch by forcing some shader color conversion functions to full float precision. - Fixed a bug in FreeCamera which would only provide a speed boost for the first frame when pressing the Shfit key. ### Added diff --git a/com.unity.render-pipelines.core/Editor/Volume/VolumeComponentEditor.cs b/com.unity.render-pipelines.core/Editor/Volume/VolumeComponentEditor.cs index 88673fe769d..dc4985dc445 100644 --- a/com.unity.render-pipelines.core/Editor/Volume/VolumeComponentEditor.cs +++ b/com.unity.render-pipelines.core/Editor/Volume/VolumeComponentEditor.cs @@ -75,6 +75,26 @@ public VolumeComponentEditorAttribute(Type componentType) /// public class VolumeComponentEditor { + class Styles + { + public static GUIContent overrideSettingText { get; } = EditorGUIUtility.TrTextContent("", "Override this setting for this volume."); + public static GUIContent allText { get; } = EditorGUIUtility.TrTextContent("ALL", "Toggle all overrides on. To maximize performances you should only toggle overrides that you actually need."); + public static GUIContent noneText { get; } = EditorGUIUtility.TrTextContent("NONE", "Toggle all overrides off."); + + public static string toggleAllText { get; } = L10n.Tr("Toggle All"); + } + + Vector2? m_OverrideToggleSize; + internal Vector2 overrideToggleSize + { + get + { + if (!m_OverrideToggleSize.HasValue) + m_OverrideToggleSize = CoreEditorStyles.smallTickbox.CalcSize(Styles.overrideSettingText); + return m_OverrideToggleSize.Value; + } + } + /// /// Specifies the this editor is drawing. /// @@ -99,10 +119,11 @@ public class VolumeComponentEditor SerializedProperty m_AdvancedMode; + List m_VolumeNotAdditionalParameters; /// /// Override this property if your editor makes use of the "More Options" feature. /// - public virtual bool hasAdvancedMode => false; + public virtual bool hasAdvancedMode => target.parameters.Count != m_VolumeNotAdditionalParameters.Count; /// /// Checks if the editor currently has the "More Options" feature toggled on. @@ -176,9 +197,18 @@ internal void Init(VolumeComponent target, Editor inspector) serializedObject = new SerializedObject(target); activeProperty = serializedObject.FindProperty("active"); m_AdvancedMode = serializedObject.FindProperty("m_AdvancedMode"); + + InitParameters(); + OnEnable(); } + void InitParameters() + { + m_VolumeNotAdditionalParameters = new List(); + VolumeComponent.FindParameters(target, m_VolumeNotAdditionalParameters, field => field.GetCustomAttribute() == null); + } + void GetFields(object o, List<(FieldInfo, SerializedProperty)> infos, SerializedProperty prop = null) { if (o == null) @@ -281,21 +311,68 @@ public virtual string GetDisplayTitle() return target.displayName == "" ? ObjectNames.NicifyVariableName(target.GetType().Name) : target.displayName; } + void AddToogleState(GUIContent content, bool state) + { + bool allOverridesSameState = AreOverridesTo(state); + if (GUILayout.Toggle(allOverridesSameState, content, CoreEditorStyles.miniLabelButton, GUILayout.ExpandWidth(false)) && !allOverridesSameState) + SetOverridesTo(state); + } + void TopRowFields() { using (new EditorGUILayout.HorizontalScope()) { - if (GUILayout.Button(EditorGUIUtility.TrTextContent("All", "Toggle all overrides on. To maximize performances you should only toggle overrides that you actually need."), CoreEditorStyles.miniLabelButton, GUILayout.Width(17f), GUILayout.ExpandWidth(false))) - SetAllOverridesTo(true); + AddToogleState(Styles.allText, true); + AddToogleState(Styles.noneText, false); + } + } + + /// + /// Checks if all the visible parameters have the given state + /// + /// The state to check + internal bool AreOverridesTo(bool state) + { + if (hasAdvancedMode && isInAdvancedMode) + return AreAllOverridesTo(state); + + for (int i = 0; i < m_VolumeNotAdditionalParameters.Count; ++i) + { + if (m_VolumeNotAdditionalParameters[i].overrideState != state) + return false; + } + return true; + } - if (GUILayout.Button(EditorGUIUtility.TrTextContent("None", "Toggle all overrides off."), CoreEditorStyles.miniLabelButton, GUILayout.Width(32f), GUILayout.ExpandWidth(false))) - SetAllOverridesTo(false); + /// + /// Sets the given state to all the visible parameters + /// + /// The state to check + internal void SetOverridesTo(bool state) + { + if (hasAdvancedMode && isInAdvancedMode) + SetAllOverridesTo(state); + else + { + Undo.RecordObject(target, Styles.toggleAllText); + target.SetOverridesTo(m_VolumeNotAdditionalParameters, state); + serializedObject.Update(); } } + internal bool AreAllOverridesTo(bool state) + { + for (int i = 0; i < target.parameters.Count; ++i) + { + if (target.parameters[i].overrideState != state) + return false; + } + return true; + } + internal void SetAllOverridesTo(bool state) { - Undo.RecordObject(target, "Toggle All"); + Undo.RecordObject(target, Styles.toggleAllText); target.SetAllOverridesTo(state); serializedObject.Update(); } @@ -423,9 +500,14 @@ protected void PropertyField(SerializedDataParameter property, GUIContent title) /// The property to draw the override checkbox for protected void DrawOverrideCheckbox(SerializedDataParameter property) { - var overrideRect = GUILayoutUtility.GetRect(17f, 17f, GUILayout.ExpandWidth(false)); - overrideRect.yMin += 4f; - property.overrideState.boolValue = GUI.Toggle(overrideRect, property.overrideState.boolValue, EditorGUIUtility.TrTextContent("", "Override this setting for this volume."), CoreEditorStyles.smallTickbox); + // Create a rect with the width of the Toggle "ALL" and the height + vspacing of the property that is being overriden + float height = EditorGUI.GetPropertyHeight(property.value) + EditorGUIUtility.standardVerticalSpacing; + var overrideRect = GUILayoutUtility.GetRect(Styles.allText, CoreEditorStyles.miniLabelButton, GUILayout.Height(height), GUILayout.ExpandWidth(false)); + + // also center vertically the checkbox + overrideRect.yMin += height * 0.5f - overrideToggleSize.y * 0.5f; + + property.overrideState.boolValue = GUI.Toggle(overrideRect, property.overrideState.boolValue, Styles.overrideSettingText, CoreEditorStyles.smallTickbox); } } } diff --git a/com.unity.render-pipelines.core/Runtime/Common/CoreAttributes.cs b/com.unity.render-pipelines.core/Runtime/Common/CoreAttributes.cs index 29f5777a4af..c06a3092d7c 100644 --- a/com.unity.render-pipelines.core/Runtime/Common/CoreAttributes.cs +++ b/com.unity.render-pipelines.core/Runtime/Common/CoreAttributes.cs @@ -13,4 +13,12 @@ public class DisplayInfoAttribute : Attribute /// Display order used in UI. public int order; } + + /// + /// Attribute used to customize UI display to allow properties only be visible when "Show Additional Properties" is selected + /// + [AttributeUsage(AttributeTargets.Field)] + public class AdditionalPropertyAttribute : Attribute + { + } } diff --git a/com.unity.render-pipelines.core/Runtime/Volume/VolumeComponent.cs b/com.unity.render-pipelines.core/Runtime/Volume/VolumeComponent.cs index 499f299939d..ad134a16105 100644 --- a/com.unity.render-pipelines.core/Runtime/Volume/VolumeComponent.cs +++ b/com.unity.render-pipelines.core/Runtime/Volume/VolumeComponent.cs @@ -81,7 +81,10 @@ public class VolumeComponent : ScriptableObject /// /// Extracts all the s defined in this class and nested classes. /// - static void GetParameters(object o, List parameters) + /// The object to find the parameters + /// The list filled with the parameters. + /// If you want to filter the parameters + internal static void FindParameters(object o, List parameters, Func filter = null) { if (o == null) return; @@ -93,9 +96,12 @@ static void GetParameters(object o, List parameters) foreach (var field in fields) { if (field.FieldType.IsSubclassOf(typeof(VolumeParameter))) - parameters.Add((VolumeParameter)field.GetValue(o)); + { + if (filter?.Invoke(field) ?? true) + parameters.Add((VolumeParameter)field.GetValue(o)); + } else if (!field.FieldType.IsArray && field.FieldType.IsClass) - GetParameters(field.GetValue(o), parameters); + FindParameters(field.GetValue(o), parameters, filter); } } @@ -109,7 +115,7 @@ protected virtual void OnEnable() { // Automatically grab all fields of type VolumeParameter for this instance var fields = new List(); - GetParameters(this, fields); + FindParameters(this, fields); parameters = fields.AsReadOnly(); foreach (var parameter in parameters) @@ -195,10 +201,14 @@ public virtual void Override(VolumeComponent state, float interpFactor) /// The value to set the state of the overrides to. public void SetAllOverridesTo(bool state) { - SetAllOverridesTo(parameters, state); + SetOverridesTo(parameters, state); } - void SetAllOverridesTo(IEnumerable enumerable, bool state) + /// + /// Sets the override state of the given parameters on this component to a given value. + /// + /// The value to set the state of the overrides to. + internal void SetOverridesTo(IEnumerable enumerable, bool state) { foreach (var prop in enumerable) { @@ -213,7 +223,7 @@ void SetAllOverridesTo(IEnumerable enumerable, bool state) .GetValue(prop, null); if (innerParams != null) - SetAllOverridesTo(innerParams, state); + SetOverridesTo(innerParams, state); } } } diff --git a/com.unity.render-pipelines.core/Tests/Editor/ReflectionUtils.cs b/com.unity.render-pipelines.core/Tests/Editor/ReflectionUtils.cs new file mode 100644 index 00000000000..d2586d4392f --- /dev/null +++ b/com.unity.render-pipelines.core/Tests/Editor/ReflectionUtils.cs @@ -0,0 +1,79 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace UnityEngine.Rendering.Tests +{ + public static class ReflectionUtils + { + /// + /// Calls a private method from a class + /// + /// The method name + /// The arguments to pass to the method + public static object Invoke(this object target, string methodName, params object[] args) + { + Assert.True(target != null, "The target could not be null"); + Assert.IsNotEmpty(methodName, "The field to set could not be null"); + + var mi = target.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); + Assert.True(mi != null, $"Could not find method `{methodName}` on object `{target}`"); + return mi.Invoke(target, args); + } + + private static FieldInfo FindField(this Type type, string fieldName) + { + FieldInfo fi = null; + + while (type != null) + { + fi = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); + + if (fi != null) break; + + type = type.BaseType; + } + + Assert.True(fi != null, $"Could not find method `{fieldName}` on object `{type}`"); + + return fi; + } + + /// + /// Sets a private field from a class + /// + /// The field to change + /// The new value + public static void SetField(this object target, string fieldName, object value) + { + Assert.True(target != null, "The target could not be null"); + Assert.IsNotEmpty(fieldName, "The field to set could not be null"); + target.GetType().FindField(fieldName).SetValue(target, value); + } + + /// + /// Gets the value of a private field from a class + /// + /// The field to get + public static object GetField(this object target, string fieldName) + { + Assert.True(target != null, "The target could not be null"); + Assert.IsNotEmpty(fieldName, "The field to set could not be null"); + return target.GetType().FindField(fieldName).GetValue(target); + } + + /// + /// Gets all the fields from a class + /// + public static IEnumerable GetFields(this object target) + { + Assert.True(target != null, "The target could not be null"); + + return target.GetType() + .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) + .OrderBy(t => t.MetadataToken); + } + } +} diff --git a/com.unity.render-pipelines.core/Tests/Editor/ReflectionUtils.cs.meta b/com.unity.render-pipelines.core/Tests/Editor/ReflectionUtils.cs.meta new file mode 100644 index 00000000000..1407d39e90c --- /dev/null +++ b/com.unity.render-pipelines.core/Tests/Editor/ReflectionUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 994ab27378e49eb45830d39c4c0b5799 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.core/Tests/Editor/Volumes.meta b/com.unity.render-pipelines.core/Tests/Editor/Volumes.meta new file mode 100644 index 00000000000..07a7f25b318 --- /dev/null +++ b/com.unity.render-pipelines.core/Tests/Editor/Volumes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 93ab3f290033d9a48b3cce3d26d93f89 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentTests.cs b/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentTests.cs new file mode 100644 index 00000000000..78dd955dd1a --- /dev/null +++ b/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentTests.cs @@ -0,0 +1,109 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEditor.Rendering; + +namespace UnityEngine.Rendering.Tests +{ + public class VolumeComponentEditorTests + { + class VolumeComponentNoAdditionalAttributes : VolumeComponent + { + public MinFloatParameter parameter = new MinFloatParameter(0f, 0f); + } + + class VolumeComponentAllAdditionalAttributes : VolumeComponent + { + [AdditionalProperty] + public MinFloatParameter parameter1 = new MinFloatParameter(0f, 0f); + + [AdditionalProperty] + public FloatParameter parameter2 = new MinFloatParameter(0f, 0f); + } + + class VolumeComponentMixedAdditionalAttributes : VolumeComponent + { + public MinFloatParameter parameter1 = new MinFloatParameter(0f, 0f); + + [AdditionalProperty] + public FloatParameter parameter2 = new MinFloatParameter(0f, 0f); + + public MinFloatParameter parameter3 = new MinFloatParameter(0f, 0f); + + [AdditionalProperty] + public FloatParameter parameter4 = new MinFloatParameter(0f, 0f); + } + + [Test] + public void TestOverridesChanges() + { + var component = ScriptableObject.CreateInstance(); + var editor = (VolumeComponentEditor)Activator.CreateInstance(typeof(VolumeComponentEditor)); + editor.Invoke("Init", component, null); + + component.SetAllOverridesTo(false); + bool allOverridesState = (bool)editor.Invoke("AreAllOverridesTo", false); + Assert.True(allOverridesState); + + component.SetAllOverridesTo(true); + + // Was the change correct? + allOverridesState = (bool)editor.Invoke("AreAllOverridesTo", true); + Assert.True(allOverridesState); + + // Enable the advance mode on the editor + component.SetField("m_AdvancedMode", true); + + // Everything is false + component.SetAllOverridesTo(false); + + // Disable the advance mode on the editor + component.SetField("m_AdvancedMode", false); + + // Now just set to true the overrides of non additional properties + editor.Invoke("SetOverridesTo", true); + + // Check that the non additional properties must be false + allOverridesState = (bool)editor.Invoke("AreAllOverridesTo", true); + Assert.False(allOverridesState); + + ScriptableObject.DestroyImmediate(component); + } + + static TestCaseData[] s_AdditionalAttributesTestCaseDatas = + { + new TestCaseData(typeof(VolumeComponentNoAdditionalAttributes)) + .Returns(Array.Empty()) + .SetName("VolumeComponentNoAdditionalAttributes"), + new TestCaseData(typeof(VolumeComponentAllAdditionalAttributes)) + .Returns(new string[2] {"parameter1", "parameter2"}) + .SetName("VolumeComponentAllAdditionalAttributes"), + new TestCaseData(typeof(VolumeComponentMixedAdditionalAttributes)) + .Returns(new string[2] {"parameter2", "parameter4"}) + .SetName("VolumeComponentMixedAdditionalAttributes"), + }; + + [Test, TestCaseSource(nameof(s_AdditionalAttributesTestCaseDatas))] + public string[] AdditionalProperties(Type volumeComponentType) + { + var component = (VolumeComponent)ScriptableObject.CreateInstance(volumeComponentType); + var editor = (VolumeComponentEditor)Activator.CreateInstance(typeof(VolumeComponentEditor)); + editor.Invoke("Init", component, null); + + var fields = component + .GetFields() + .Where(f => f.GetCustomAttribute() != null) + .Select(f => f.Name) + .ToArray(); + + var notAdditionalParameters = editor.GetField("m_VolumeNotAdditionalParameters") as List; + Assert.True(fields.Count() + notAdditionalParameters.Count == component.parameters.Count); + + ScriptableObject.DestroyImmediate(component); + + return fields; + } + } +} diff --git a/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentTests.cs.meta b/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentTests.cs.meta new file mode 100644 index 00000000000..3c9cb09e32d --- /dev/null +++ b/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0fd9ee276a1023e439cf7a9c393195fa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/BloomEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/BloomEditor.cs index c1d8a874e7e..4803709e61b 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/BloomEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/BloomEditor.cs @@ -20,8 +20,6 @@ sealed class BloomEditor : VolumeComponentWithQualityEditor SerializedDataParameter m_Resolution; SerializedDataParameter m_Anamorphic; - public override bool hasAdvancedMode => true; - public override void OnEnable() { var o = new PropertyFetcher(serializedObject); diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs index a95cb272639..197308bea71 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/DepthOfFieldEditor.cs @@ -46,8 +46,6 @@ static partial class Styles SerializedDataParameter m_Resolution; SerializedDataParameter m_PhysicallyBased; - public override bool hasAdvancedMode => true; - public override void OnEnable() { var o = new PropertyFetcher(serializedObject); diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ExposureEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ExposureEditor.cs index 1fdcb1f2168..4e7d2d38aa9 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ExposureEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/ExposureEditor.cs @@ -41,8 +41,6 @@ sealed class ExposureEditor : VolumeComponentEditor static readonly string[] s_MidGrayNames = { "Grey 12.5%", "Grey 14.0%", "Grey 18.0%" }; - public override bool hasAdvancedMode => true; - public override void OnEnable() { var o = new PropertyFetcher(serializedObject); diff --git a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/MotionBlurEditor.cs b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/MotionBlurEditor.cs index 5c22c2aa017..faf043aa511 100644 --- a/com.unity.render-pipelines.high-definition/Editor/PostProcessing/MotionBlurEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/PostProcessing/MotionBlurEditor.cs @@ -23,8 +23,6 @@ sealed class MotionBlurEditor : VolumeComponentWithQualityEditor SerializedDataParameter m_DepthCmpScale; SerializedDataParameter m_CameraMotionBlur; - public override bool hasAdvancedMode => true; - public override void OnEnable() { var o = new PropertyFetcher(serializedObject); diff --git a/com.unity.render-pipelines.high-definition/Editor/Sky/AtmosphericScattering/FogEditor.cs b/com.unity.render-pipelines.high-definition/Editor/Sky/AtmosphericScattering/FogEditor.cs index ad385a022d0..e5b4c3b1967 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Sky/AtmosphericScattering/FogEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Sky/AtmosphericScattering/FogEditor.cs @@ -44,8 +44,6 @@ class FogEditor : VolumeComponentWithQualityEditor static GUIContent s_EnableVolumetricFog = new GUIContent("Volumetric Fog", "When enabled, activates volumetric fog."); static GUIContent s_DepthExtentLabel = new GUIContent("Volumetric Fog Distance", "Sets the distance (in meters) from the Camera's Near Clipping Plane to the back of the Camera's volumetric lighting buffer. The lower the distance is, the higher the fog quality is."); - public override bool hasAdvancedMode => true; - public override void OnEnable() { var o = new PropertyFetcher(serializedObject); diff --git a/com.unity.render-pipelines.high-definition/Editor/Sky/CloudSystem/CloudLayer/CloudLayerEditor.cs b/com.unity.render-pipelines.high-definition/Editor/Sky/CloudSystem/CloudLayer/CloudLayerEditor.cs index 95e2cc5cb29..9a7f5de8462 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Sky/CloudSystem/CloudLayer/CloudLayerEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Sky/CloudSystem/CloudLayer/CloudLayerEditor.cs @@ -13,8 +13,6 @@ class CloudLayerEditor : VolumeComponentEditor readonly GUIContent sunLabel = new GUIContent("Sun light", "The main directional light, used for lighting and shadow casting."); readonly GUIContent shadowTiling = new GUIContent("Shadow Tiling", "The tiling of the cloud shadows texture. Controlled by the cookie size parameter on the sun light."); - public override bool hasAdvancedMode => true; - struct CloudMapParameter { public SerializedDataParameter cloudMap; diff --git a/com.unity.render-pipelines.high-definition/Editor/Sky/HDRISky/HDRISkyEditor.cs b/com.unity.render-pipelines.high-definition/Editor/Sky/HDRISky/HDRISkyEditor.cs index 08b2e42cf82..dc87d92ce5c 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Sky/HDRISky/HDRISkyEditor.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Sky/HDRISky/HDRISkyEditor.cs @@ -41,7 +41,6 @@ class HDRISkyEditor RTHandle m_IntensityTexture; Material m_IntegrateHDRISkyMaterial; // Compute the HDRI sky intensity in lux for the skybox Texture2D m_ReadBackTexture; - public override bool hasAdvancedMode => true; public override void OnEnable() { diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/Fog.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/Fog.cs index 235f6b4afd5..42825e703ab 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/Fog.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/Fog.cs @@ -27,12 +27,15 @@ public class Fog : VolumeComponentWithQuality [Tooltip("Sets the maximum fog distance HDRP uses when it shades the skybox or the Far Clipping Plane of the Camera.")] public MinFloatParameter maxFogDistance = new MinFloatParameter(5000.0f, 0.0f); /// Controls the maximum mip map HDRP uses for mip fog (0 is the lowest mip and 1 is the highest mip). + [AdditionalProperty] [Tooltip("Controls the maximum mip map HDRP uses for mip fog (0 is the lowest mip and 1 is the highest mip).")] public ClampedFloatParameter mipFogMaxMip = new ClampedFloatParameter(0.5f, 0.0f, 1.0f); /// Sets the distance at which HDRP uses the minimum mip image of the blurred sky texture as the fog color. + [AdditionalProperty] [Tooltip("Sets the distance at which HDRP uses the minimum mip image of the blurred sky texture as the fog color.")] public MinFloatParameter mipFogNear = new MinFloatParameter(0.0f, 0.0f); /// Sets the distance at which HDRP uses the maximum mip image of the blurred sky texture as the fog color. + [AdditionalProperty] [Tooltip("Sets the distance at which HDRP uses the maximum mip image of the blurred sky texture as the fog color.")] public MinFloatParameter mipFogFar = new MinFloatParameter(1000.0f, 0.0f); @@ -64,8 +67,10 @@ public class Fog : VolumeComponentWithQuality // Advanced parameters /// Controls the angular distribution of scattered light. 0 is isotropic, 1 is forward scattering, and -1 is backward scattering. + [AdditionalProperty] public ClampedFloatParameter anisotropy = new ClampedFloatParameter(0.0f, -1.0f, 1.0f); /// Controls the distribution of slices along the Camera's focal axis. 0 is exponential distribution and 1 is linear distribution. + [AdditionalProperty] [Tooltip("Controls the distribution of slices along the Camera's focal axis. 0 is exponential distribution and 1 is linear distribution.")] public ClampedFloatParameter sliceDistributionUniformity = new ClampedFloatParameter(0.75f, 0, 1); @@ -88,14 +93,17 @@ public FogControl fogControlMode } set { m_FogControlMode.value = value; } } + [AdditionalProperty] [SerializeField, FormerlySerializedAs("fogControlMode")] [Tooltip("Specifies which method to use to control the performance and quality of the volumetric fog.")] private FogControlParameter m_FogControlMode = new FogControlParameter(FogControl.Balance); /// Stores the resolution of the volumetric buffer (3D texture) along the x-axis and y-axis relative to the resolution of the screen. + [AdditionalProperty] [Tooltip("Controls the resolution of the volumetric buffer (3D texture) along the x-axis and y-axis relative to the resolution of the screen.")] public ClampedFloatParameter screenResolutionPercentage = new ClampedFloatParameter(optimalFogScreenResolutionPercentage, minFogScreenResolutionPercentage, maxFogScreenResolutionPercentage); /// Number of slices of the volumetric buffer (3D texture) along the camera's focal axis. + [AdditionalProperty] [Tooltip("Controls the number of slices to use the volumetric buffer (3D texture) along the camera's focal axis.")] public ClampedIntParameter volumeSliceCount = new ClampedIntParameter(64, 1, maxFogSliceCount); @@ -112,6 +120,7 @@ public float volumetricFogBudget } set { m_VolumetricFogBudget.value = value; } } + [AdditionalProperty] [SerializeField, FormerlySerializedAs("volumetricFogBudget")] [Tooltip("Controls the performance to quality ratio of the volumetric fog. A value of 0 being the least resource-intensive and a value of 1 being the highest quality.")] private ClampedFloatParameter m_VolumetricFogBudget = new ClampedFloatParameter(0.25f, 0.0f, 1.0f); @@ -129,11 +138,13 @@ public float resolutionDepthRatio } set { m_ResolutionDepthRatio.value = value; } } + [AdditionalProperty] [SerializeField, FormerlySerializedAs("resolutionDepthRatio")] [Tooltip("Controls how Unity shares resources between Screen (x-axis and y-axis) and Depth (z-axis) resolutions.")] public ClampedFloatParameter m_ResolutionDepthRatio = new ClampedFloatParameter(0.5f, 0.0f, 1.0f); /// Indicates whether Unity includes or excludes non-directional light types when it evaluates the volumetric fog. Including non-directional lights increases the resource intensity of the effect. + [AdditionalProperty] [Tooltip("When enabled, HDRP only includes directional Lights when it evaluates volumetric fog.")] public BoolParameter directionalLightsOnly = new BoolParameter(false); diff --git a/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.cs b/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.cs index af3599f6701..44de820c7bd 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Lighting/ScreenSpaceLighting/AmbientOcclusion.cs @@ -204,6 +204,7 @@ public int directionCount [SerializeField, FormerlySerializedAs("maximumRadiusInPixels")] private ClampedIntParameter m_MaximumRadiusInPixels = new ClampedIntParameter(40, 16, 256); // Temporal only parameter + [AdditionalProperty] [SerializeField, FormerlySerializedAs("bilateralUpsample")] private BoolParameter m_BilateralUpsample = new BoolParameter(true); // Non-temporal only parameters diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/Bloom.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/Bloom.cs index eb229c903d7..b86961ed2d6 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/Bloom.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/Bloom.cs @@ -68,6 +68,7 @@ public sealed class Bloom : VolumeComponentWithQuality, IPostProcessComponent /// When enabled, bloom stretches horizontally depending on the current physical Camera's Anamorphism property value. /// [Tooltip("When enabled, bloom stretches horizontally depending on the current physical Camera's Anamorphism property value.")] + [AdditionalProperty] public BoolParameter anamorphic = new BoolParameter(true); /// @@ -131,14 +132,17 @@ public bool highQualityFiltering set { m_HighQualityFiltering.value = value; } } + [AdditionalProperty] [Tooltip("Specifies the resolution at which HDRP processes the effect. Quarter resolution is less resource intensive but can result in aliasing artifacts.")] [SerializeField, FormerlySerializedAs("resolution")] private BloomResolutionParameter m_Resolution = new BloomResolutionParameter(BloomResolution.Half); + [AdditionalProperty] [Tooltip("When enabled, bloom uses multiple bilinear samples for the prefiltering pass.")] [SerializeField] private BoolParameter m_HighQualityPrefiltering = new BoolParameter(false); + [AdditionalProperty] [Tooltip("When enabled, bloom uses bicubic sampling instead of bilinear sampling for the upsampling passes.")] [SerializeField, FormerlySerializedAs("highQualityFiltering")] private BoolParameter m_HighQualityFiltering = new BoolParameter(true); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/DepthOfField.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/DepthOfField.cs index a418592494e..a5848281405 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/DepthOfField.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/DepthOfField.cs @@ -269,15 +269,17 @@ public DepthOfFieldResolution resolution // ------------------------------------------- // Advanced settings // - + [AdditionalProperty] [Tooltip("When enabled, HDRP uses bicubic filtering instead of bilinear filtering for the depth of field effect.")] [SerializeField, FormerlySerializedAs("highQualityFiltering")] BoolParameter m_HighQualityFiltering = new BoolParameter(true); + [AdditionalProperty] [Tooltip("Specifies the resolution at which HDRP processes the depth of field effect.")] [SerializeField, FormerlySerializedAs("resolution")] DepthOfFieldResolutionParameter m_Resolution = new DepthOfFieldResolutionParameter(DepthOfFieldResolution.Half); + [AdditionalProperty] [SerializeField] BoolParameter m_PhysicallyBased = new BoolParameter(false); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/Exposure.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/Exposure.cs index 2c8ccad9052..220a2324012 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/Exposure.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/Exposure.cs @@ -124,6 +124,7 @@ public sealed class Exposure : VolumeComponent, IPostProcessComponent /// Sets the desired Mid gray level used by the auto exposure (i.e. to what grey value the auto exposure system maps the average scene luminance). /// Note that the lens model used in HDRP is not of a perfect lens, hence it will not map precisely to the selected value. /// + [AdditionalProperty] [Tooltip("Sets the desired Mid gray level used by the auto exposure (i.e. to what grey value the auto exposure system maps the average scene luminance).")] public TargetMidGrayParameter targetMidGray = new TargetMidGrayParameter(TargetMidGray.Grey125); @@ -144,11 +145,13 @@ public sealed class Exposure : VolumeComponent, IPostProcessComponent /// /// All pixels below this threshold (in EV100 units) will be assigned a weight of 0 in the metering mask. /// + [AdditionalProperty] [Tooltip("All pixels below this threshold (in EV100 units) will be assigned a weight of 0 in the metering mask.")] public FloatParameter maskMinIntensity = new FloatParameter(-30.0f); /// /// All pixels above this threshold (in EV100 units) will be assigned a weight of 0 in the metering mask. /// + [AdditionalProperty] [Tooltip("All pixels above this threshold (in EV100 units) will be assigned a weight of 0 in the metering mask.")] public FloatParameter maskMaxIntensity = new FloatParameter(30.0f); diff --git a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/MotionBlur.cs b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/MotionBlur.cs index 9b390a89df4..a3a8baf78c1 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/MotionBlur.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Components/MotionBlur.cs @@ -76,6 +76,7 @@ public sealed class MotionBlur : VolumeComponentWithQuality, IPostProcessCompone /// /// If toggled on camera rotation can be clamped differently. /// + [AdditionalProperty] [Tooltip("If toggled off, the motion caused by the camera is not considered when doing motion blur.")] public BoolParameter cameraMotionBlur = new BoolParameter(true); @@ -84,30 +85,35 @@ public sealed class MotionBlur : VolumeComponentWithQuality, IPostProcessCompone /// Determine how the component of the motion vectors coming from the camera is clamped. It is important to remember that clamping the camera component separately, velocities relative to camera might change too (e.g. an object parented to a camera /// when the camera moves might not have a 0 motion vector anymore). /// + [AdditionalProperty] [Tooltip("Determine if and how the component of the motion vectors coming from the camera is clamped in a special fashion.")] public CameraClampModeParameter specialCameraClampMode = new CameraClampModeParameter(CameraClampMode.None); /// /// Sets the maximum length, as a fraction of the screen's full resolution, that the motion vectors resulting from Camera movement can have. Only valid if specialCameraClampMode is set to CameraClampMode.FullCameraMotionVector. /// + [AdditionalProperty] [Tooltip("Sets the maximum length, as a fraction of the screen's full resolution, that the motion vectors resulting from Camera can have.")] public ClampedFloatParameter cameraVelocityClamp = new ClampedFloatParameter(0.05f, 0.0f, 0.3f); /// /// Sets the maximum length, as a fraction of the screen's full resolution, that the motion vectors resulting from Camera can have. Only valid if specialCameraClampMode is set to CameraClampMode.Translation or CameraClampMode.SeparateTranslationAndRotation. /// + [AdditionalProperty] [Tooltip("Sets the maximum length, as a fraction of the screen's full resolution, that the motion vectors resulting from Camera can have.")] public ClampedFloatParameter cameraTranslationVelocityClamp = new ClampedFloatParameter(0.05f, 0.0f, 0.3f); /// /// Sets the maximum length, as a fraction of the screen's full resolution, that the motion vectors resulting from Camera rotation can have. Only valid if specialCameraClampMode is set to CameraClampMode.Rotation or CameraClampMode.SeparateTranslationAndRotation. /// + [AdditionalProperty] [Tooltip("Sets the maximum length, as a fraction of the screen's full resolution, that the motion vectors resulting from Camera rotation can have.")] public ClampedFloatParameter cameraRotationVelocityClamp = new ClampedFloatParameter(0.03f, 0.0f, 0.3f); /// /// Value used for the depth based weighting of samples. Tweak if unwanted leak of background onto foreground or viceversa is detected. /// + [AdditionalProperty] [Tooltip("Value used for the depth based weighting of samples. Tweak if unwanted leak of background onto foreground or viceversa is detected.")] public ClampedFloatParameter depthComparisonExtent = new ClampedFloatParameter(1.0f, 0.0f, 20.0f); diff --git a/com.unity.render-pipelines.high-definition/Runtime/Sky/CloudSystem/CloudLayer/CloudLayer.cs b/com.unity.render-pipelines.high-definition/Runtime/Sky/CloudSystem/CloudLayer/CloudLayer.cs index 49c35ec9c91..4c4d6929c8c 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Sky/CloudSystem/CloudLayer/CloudLayer.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Sky/CloudSystem/CloudLayer/CloudLayer.cs @@ -92,11 +92,13 @@ public class CloudLayer : CloudSettings [Tooltip("Controls the global opacity of the cloud layer.")] public ClampedFloatParameter opacity = new ClampedFloatParameter(1.0f, 0.0f, 1.0f); /// Enable to cover only the upper part of the sky. + [AdditionalProperty] [Tooltip("Check this box if the cloud layer covers only the upper part of the sky.")] public BoolParameter upperHemisphereOnly = new BoolParameter(true); /// Choose the number of cloud layers. public VolumeParameter layers = new VolumeParameter(); /// Choose the resolution of the baked cloud texture. + [AdditionalProperty] [Tooltip("Specifies the resolution of the texture HDRP uses to represent the clouds.")] public CloudLayerEnumParameter resolution = new CloudLayerEnumParameter(CloudResolution.CloudResolution1024); @@ -108,6 +110,7 @@ public class CloudLayer : CloudSettings [Tooltip("Controls the tint of the cloud shadows.")] public ColorParameter shadowTint = new ColorParameter(Color.black, false, false, true); /// Choose the resolution of the texture for the cloud shadows. + [AdditionalProperty] [Tooltip("Specifies the resolution of the texture HDRP uses to represent the cloud shadows.")] public CloudLayerEnumParameter shadowResolution = new CloudLayerEnumParameter(CloudShadowsResolution.CloudShadowsResolution128); diff --git a/com.unity.render-pipelines.high-definition/Runtime/Sky/HDRISky/HDRISky.cs b/com.unity.render-pipelines.high-definition/Runtime/Sky/HDRISky/HDRISky.cs index 88798fb37e4..049d153968e 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Sky/HDRISky/HDRISky.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/Sky/HDRISky/HDRISky.cs @@ -35,42 +35,55 @@ public class HDRISky : SkySettings public MinFloatParameter scrollSpeed = new MinFloatParameter(2.0f, 0.0f); /// Enable Backplate to have it visible. + [AdditionalProperty] [Tooltip("Enable or disable the backplate.")] public BoolParameter enableBackplate = new BoolParameter(false); /// Backplate Type {Disc, Rectangle, Ellipse, Infinite (Plane)}. + [AdditionalProperty] [Tooltip("Backplate type.")] public BackplateTypeParameter backplateType = new BackplateTypeParameter(BackplateType.Disc); /// Define the ground level of the Backplate. + [AdditionalProperty] [Tooltip("Define the ground level of the Backplate.")] public FloatParameter groundLevel = new FloatParameter(0.0f); /// Extent of the Backplate (if circle only the X value is considered). + [AdditionalProperty] [Tooltip("Extent of the Backplate (if circle only the X value is considered).")] public Vector2Parameter scale = new Vector2Parameter(Vector2.one * 32.0f); /// Backplate's projection distance to varying the cubemap projection on the plate. + [AdditionalProperty] [Tooltip("Backplate's projection distance to varying the cubemap projection on the plate.")] public MinFloatParameter projectionDistance = new MinFloatParameter(16.0f, 1e-7f); /// Backplate rotation parameter for the geometry. + [AdditionalProperty] [Tooltip("Backplate rotation parameter for the geometry.")] public ClampedFloatParameter plateRotation = new ClampedFloatParameter(0.0f, 0.0f, 360.0f); /// Backplate rotation parameter for the projected texture. + [AdditionalProperty] [Tooltip("Backplate rotation parameter for the projected texture.")] public ClampedFloatParameter plateTexRotation = new ClampedFloatParameter(0.0f, 0.0f, 360.0f); /// Backplate projection offset on the plane. + [AdditionalProperty] [Tooltip("Backplate projection offset on the plane.")] public Vector2Parameter plateTexOffset = new Vector2Parameter(Vector2.zero); /// Backplate blend parameter to blend the edge of the backplate with the background. + [AdditionalProperty] [Tooltip("Backplate blend parameter to blend the edge of the backplate with the background.")] public ClampedFloatParameter blendAmount = new ClampedFloatParameter(0.0f, 0.0f, 100.0f); /// Backplate Shadow Tint projected on the plane. + [AdditionalProperty] [Tooltip("Backplate Shadow Tint projected on the plane.")] public ColorParameter shadowTint = new ColorParameter(Color.grey); /// Allow backplate to receive shadow from point light. + [AdditionalProperty] [Tooltip("Allow backplate to receive shadow from point light.")] public BoolParameter pointLightShadow = new BoolParameter(false); /// Allow backplate to receive shadow from directional light. + [AdditionalProperty] [Tooltip("Allow backplate to receive shadow from directional light.")] public BoolParameter dirLightShadow = new BoolParameter(false); /// Allow backplate to receive shadow from Area light. + [AdditionalProperty] [Tooltip("Allow backplate to receive shadow from Area light.")] public BoolParameter rectLightShadow = new BoolParameter(false); diff --git a/com.unity.render-pipelines.high-definition/Tests/Editor/Volumes.meta b/com.unity.render-pipelines.high-definition/Tests/Editor/Volumes.meta new file mode 100644 index 00000000000..861f3bb5683 --- /dev/null +++ b/com.unity.render-pipelines.high-definition/Tests/Editor/Volumes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d3b76d1b56a702a46a012797c42721d1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From abf265f0e5a5f27c0570070834d4a6a39b3dea8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20V=C3=A1zquez?= Date: Tue, 26 Jan 2021 12:13:20 +0100 Subject: [PATCH 2/2] Updates from QA review --- .../Editor/Volume/VolumeComponentEditor.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.core/Editor/Volume/VolumeComponentEditor.cs b/com.unity.render-pipelines.core/Editor/Volume/VolumeComponentEditor.cs index dc4985dc445..26d41bf4fab 100644 --- a/com.unity.render-pipelines.core/Editor/Volume/VolumeComponentEditor.cs +++ b/com.unity.render-pipelines.core/Editor/Volume/VolumeComponentEditor.cs @@ -500,12 +500,13 @@ protected void PropertyField(SerializedDataParameter property, GUIContent title) /// The property to draw the override checkbox for protected void DrawOverrideCheckbox(SerializedDataParameter property) { - // Create a rect with the width of the Toggle "ALL" and the height + vspacing of the property that is being overriden + // Create a rect the height + vspacing of the property that is being overriden float height = EditorGUI.GetPropertyHeight(property.value) + EditorGUIUtility.standardVerticalSpacing; var overrideRect = GUILayoutUtility.GetRect(Styles.allText, CoreEditorStyles.miniLabelButton, GUILayout.Height(height), GUILayout.ExpandWidth(false)); // also center vertically the checkbox overrideRect.yMin += height * 0.5f - overrideToggleSize.y * 0.5f; + overrideRect.xMin += overrideToggleSize.x * 0.5f; property.overrideState.boolValue = GUI.Toggle(overrideRect, property.overrideState.boolValue, Styles.overrideSettingText, CoreEditorStyles.smallTickbox); }