protected void PropertyField(SerializedParameterOverride property, GUIContent title) { using (new EditorGUILayout.HorizontalScope()) { bool overrideState = property.overrideState.boolValue; // Override checkbox var overrideRect = GUILayoutUtility.GetRect(17f, 17f, GUILayout.ExpandWidth(false)); overrideRect.yMin += 4f; var oldColor = GUI.color; GUI.color = new Color(0.8f, 0.8f, 0.8f, 0.8f); overrideState = GUI.Toggle(overrideRect, overrideState, EditorUtilities.GetContent("|Override this setting"), Styling.smallTickbox); GUI.color = oldColor; property.overrideState.boolValue = overrideState; DoProperty(property, overrideState, title); } }
void TopRowFields() { using (new EditorGUILayout.HorizontalScope()) { if (GUILayout.Button(EditorUtilities.GetContent("All|Toggle all overrides on"), Styling.miniLabelButton, GUILayout.Width(17f), GUILayout.ExpandWidth(false))) { SetAllOverridesTo(true); } if (GUILayout.Button(EditorUtilities.GetContent("None|Toggle all overrides off"), Styling.miniLabelButton, GUILayout.Width(32f), GUILayout.ExpandWidth(false))) { SetAllOverridesTo(false); } GUILayout.FlexibleSpace(); var property = m_Enabled.Copy(); property.Next(true); bool enabled = property.boolValue; enabled = GUILayout.Toggle(enabled, EditorUtilities.GetContent("On|Enable this effect"), EditorStyles.miniButtonLeft, GUILayout.Width(35f), GUILayout.ExpandWidth(false)); enabled = !GUILayout.Toggle(!enabled, EditorUtilities.GetContent("Off|Disable this effect"), EditorStyles.miniButtonRight, GUILayout.Width(35f), GUILayout.ExpandWidth(false)); property.boolValue = enabled; } }
void CurveOverrideToggle(SerializedProperty overrideProp) { overrideProp.boolValue = GUILayout.Toggle(overrideProp.boolValue, EditorUtilities.GetContent("Override"), EditorStyles.toolbarButton); }
void DoStandardModeGUI(bool hdr) { if (!hdr) { PropertyField(m_LdrLut); var lut = (target as ColorGrading).ldrLut.value; CheckLutImportSettings(lut); } if (hdr) { EditorGUILayout.Space(); EditorUtilities.DrawHeaderLabel("Tonemapping"); PropertyField(m_Tonemapper); if (m_Tonemapper.value.intValue == (int)Tonemapper.Custom) { DrawCustomToneCurve(); PropertyField(m_ToneCurveToeStrength); PropertyField(m_ToneCurveToeLength); PropertyField(m_ToneCurveShoulderStrength); PropertyField(m_ToneCurveShoulderLength); PropertyField(m_ToneCurveShoulderAngle); PropertyField(m_ToneCurveGamma); } } EditorGUILayout.Space(); EditorUtilities.DrawHeaderLabel("White Balance"); PropertyField(m_Temperature); PropertyField(m_Tint); EditorGUILayout.Space(); EditorUtilities.DrawHeaderLabel("Tone"); if (hdr) { PropertyField(m_PostExposure); } PropertyField(m_ColorFilter); PropertyField(m_HueShift); PropertyField(m_Saturation); if (!hdr) { PropertyField(m_Brightness); } PropertyField(m_Contrast); EditorGUILayout.Space(); int currentChannel = GlobalSettings.currentChannelMixer; using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.PrefixLabel("Channel Mixer", GUIStyle.none, Styling.labelHeader); EditorGUI.BeginChangeCheck(); { using (new EditorGUILayout.HorizontalScope()) { GUILayoutUtility.GetRect(9f, 18f, GUILayout.ExpandWidth(false)); // Dirty hack to do proper right column alignement if (GUILayout.Toggle(currentChannel == 0, EditorUtilities.GetContent("Red|Red output channel."), EditorStyles.miniButtonLeft)) { currentChannel = 0; } if (GUILayout.Toggle(currentChannel == 1, EditorUtilities.GetContent("Green|Green output channel."), EditorStyles.miniButtonMid)) { currentChannel = 1; } if (GUILayout.Toggle(currentChannel == 2, EditorUtilities.GetContent("Blue|Blue output channel."), EditorStyles.miniButtonRight)) { currentChannel = 2; } } } if (EditorGUI.EndChangeCheck()) { GUI.FocusControl(null); } } GlobalSettings.currentChannelMixer = currentChannel; if (currentChannel == 0) { PropertyField(m_MixerRedOutRedIn); PropertyField(m_MixerRedOutGreenIn); PropertyField(m_MixerRedOutBlueIn); } else if (currentChannel == 1) { PropertyField(m_MixerGreenOutRedIn); PropertyField(m_MixerGreenOutGreenIn); PropertyField(m_MixerGreenOutBlueIn); } else { PropertyField(m_MixerBlueOutRedIn); PropertyField(m_MixerBlueOutGreenIn); PropertyField(m_MixerBlueOutBlueIn); } EditorGUILayout.Space(); EditorUtilities.DrawHeaderLabel("Trackballs"); using (new EditorGUILayout.HorizontalScope()) { PropertyField(m_Lift); GUILayout.Space(4f); PropertyField(m_Gamma); GUILayout.Space(4f); PropertyField(m_Gain); } EditorGUILayout.Space(); EditorUtilities.DrawHeaderLabel("Grading Curves"); DoCurvesGUI(hdr); }
public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.LabelField(EditorUtilities.GetContent("Volume blending"), EditorStyles.boldLabel); EditorGUI.indentLevel++; { // The layout system sort of break alignement when mixing inspector fields with // custom layouted fields, do the layout manually instead var indentOffset = EditorGUI.indentLevel * 15f; var lineRect = GUILayoutUtility.GetRect(1, EditorGUIUtility.singleLineHeight); var labelRect = new Rect(lineRect.x, lineRect.y, EditorGUIUtility.labelWidth - indentOffset, lineRect.height); var fieldRect = new Rect(labelRect.xMax, lineRect.y, lineRect.width - labelRect.width - 60f, lineRect.height); var buttonRect = new Rect(fieldRect.xMax, lineRect.y, 60f, lineRect.height); EditorGUI.PrefixLabel(labelRect, EditorUtilities.GetContent("Trigger|A transform that will act as a trigger for volume blending.")); m_VolumeTrigger.objectReferenceValue = (Transform)EditorGUI.ObjectField(fieldRect, m_VolumeTrigger.objectReferenceValue, typeof(Transform), false); if (GUI.Button(buttonRect, EditorUtilities.GetContent("This|Assigns the current GameObject as a trigger."), EditorStyles.miniButton)) { m_VolumeTrigger.objectReferenceValue = m_Target.transform; } if (m_VolumeTrigger.objectReferenceValue == null) { EditorGUILayout.HelpBox("No trigger has been set, the camera will only be affected by global volumes.", MessageType.Info); } EditorGUILayout.PropertyField(m_VolumeLayer, EditorUtilities.GetContent("Layer|This camera will only be affected by volumes in the selected scene-layers.")); int mask = m_VolumeLayer.intValue; if (mask == 0) { EditorGUILayout.HelpBox("No layer has been set, the trigger will never be affected by volumes.", MessageType.Warning); } else if (mask == -1 || ((mask & 1) != 0)) { EditorGUILayout.HelpBox("Do not use \"Everything\" or \"Default\" as a layer mask as it will slow down the volume blending process! Put post-processing volumes in their own dedicated layer for best performances.", MessageType.Warning); } } EditorGUI.indentLevel--; EditorGUILayout.Space(); EditorGUILayout.LabelField(EditorUtilities.GetContent("Anti-aliasing"), EditorStyles.boldLabel); EditorGUI.indentLevel++; { m_AntialiasingMode.intValue = EditorGUILayout.Popup(EditorUtilities.GetContent("Mode|The anti-aliasing method to use. FXAA is fast but low quality. SMAA works well for non-HDR scenes. TAA is a bit slower but higher quality and works well with HDR."), m_AntialiasingMode.intValue, s_AntialiasingMethodNames); if (m_AntialiasingMode.intValue == (int)PostProcessLayer.Antialiasing.TemporalAntialiasing) { if (RuntimeUtilities.isSinglePassStereoEnabled) { EditorGUILayout.HelpBox("TAA doesn't work with Single-pass stereo rendering.", MessageType.Warning); } EditorGUILayout.PropertyField(m_TaaJitterSpread); EditorGUILayout.PropertyField(m_TaaStationaryBlending); EditorGUILayout.PropertyField(m_TaaMotionBlending); EditorGUILayout.PropertyField(m_TaaSharpen); } else if (m_AntialiasingMode.intValue == (int)PostProcessLayer.Antialiasing.SubpixelMorphologicalAntialiasing) { if (RuntimeUtilities.isSinglePassStereoEnabled) { EditorGUILayout.HelpBox("SMAA doesn't work with Single-pass stereo rendering.", MessageType.Warning); } } else if (m_AntialiasingMode.intValue == (int)PostProcessLayer.Antialiasing.FastApproximateAntialiasing) { EditorGUILayout.PropertyField(m_FxaaMobileOptimized); } } EditorGUI.indentLevel--; EditorGUILayout.Space(); EditorGUILayout.LabelField(EditorUtilities.GetContent("Debug Layer"), EditorStyles.boldLabel); EditorGUI.indentLevel++; { EditorGUILayout.PropertyField(m_DebugDisplay, EditorUtilities.GetContent("Display|Toggle visibility of the debug layer on & off in the Game View.")); if (m_DebugDisplay.boolValue) { if (!SystemInfo.supportsComputeShaders) { EditorGUILayout.HelpBox("The debug layer only works on compute-shader enabled platforms.", MessageType.Info); } EditorGUILayout.PropertyField(m_DebugMonitor, EditorUtilities.GetContent("Monitor|The real-time monitor to display on the debug layer.")); EditorGUILayout.PropertyField(m_DebugLightMeter, EditorUtilities.GetContent("HDR Light Meter|Light metering utility used to setup auto exposure. Note that it will only display correct values when using a full-HDR workflow (HDR camera, HDR/Custom color grading).")); } } EditorGUI.indentLevel--; EditorGUILayout.Space(); // Toolkit EditorUtilities.DrawSplitter(); GlobalSettings.showLayerToolkit = EditorUtilities.DrawHeader("Toolkit", GlobalSettings.showLayerToolkit); if (GlobalSettings.showLayerToolkit) { EditorGUILayout.Space(); if (GUILayout.Button(EditorUtilities.GetContent("Export frame to EXR..."), EditorStyles.miniButton)) { var menu = new GenericMenu(); menu.AddItem(EditorUtilities.GetContent("Full Frame (as displayed)"), false, () => ExportFrameToExr(ExportMode.FullFrame)); menu.AddItem(EditorUtilities.GetContent("Disable post-processing"), false, () => ExportFrameToExr(ExportMode.DisablePost)); menu.AddItem(EditorUtilities.GetContent("Break before Color Grading (Linear)"), false, () => ExportFrameToExr(ExportMode.BreakBeforeColorGradingLinear)); menu.AddItem(EditorUtilities.GetContent("Break before Color Grading (Log)"), false, () => ExportFrameToExr(ExportMode.BreakBeforeColorGradingLog)); menu.ShowAsContext(); } if (GUILayout.Button(EditorUtilities.GetContent("Select all layer volumes|Selects all the volumes that will influence this layer."), EditorStyles.miniButton)) { var volumes = RuntimeUtilities.GetAllSceneObjects <PostProcessVolume>() .Where(x => (m_VolumeLayer.intValue & (1 << x.gameObject.layer)) != 0) .Select(x => x.gameObject) .Cast <UnityEngine.Object>() .ToArray(); if (volumes.Length > 0) { Selection.objects = volumes; } } if (GUILayout.Button(EditorUtilities.GetContent("Select all active volumes|Selects all volumes currently affecting the layer."), EditorStyles.miniButton)) { var volumes = new List <PostProcessVolume>(); PostProcessManager.instance.GetActiveVolumes(m_Target, volumes); if (volumes.Count > 0) { Selection.objects = volumes .Select(x => x.gameObject) .Cast <UnityEngine.Object>() .ToArray(); } } EditorGUILayout.Space(); } // Custom user effects sorter EditorUtilities.DrawSplitter(); GlobalSettings.showCustomSorter = EditorUtilities.DrawHeader("Custom Effect Sorting", GlobalSettings.showCustomSorter); if (GlobalSettings.showCustomSorter) { EditorGUILayout.Space(); bool anyList = false; if (m_CustomLists != null) { foreach (var kvp in m_CustomLists) { var list = kvp.Value; // Skip empty lists to avoid polluting the inspector if (list.count == 0) { continue; } list.DoLayoutList(); anyList = true; } } if (!anyList) { EditorGUILayout.HelpBox("No custom effect loaded.", MessageType.Info); EditorGUILayout.Space(); } } EditorUtilities.DrawSplitter(); EditorGUILayout.Space(); serializedObject.ApplyModifiedProperties(); }
protected void PropertyField(SerializedParameterOverride property) { var title = EditorUtilities.GetContent(property.displayName); PropertyField(property, title); }
public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(m_IsGlobal); if (!m_IsGlobal.boolValue) // Blend radius is not needed for global volumes { EditorGUILayout.PropertyField(m_BlendRadius); } EditorGUILayout.PropertyField(m_Weight); EditorGUILayout.PropertyField(m_Priority); bool assetHasChanged = false; bool showCopy = m_Profile.objectReferenceValue != null; // The layout system sort of break alignement when mixing inspector fields with custom // layouted fields, do the layout manually instead int buttonWidth = showCopy ? 45 : 60; float indentOffset = EditorGUI.indentLevel * 15f; var lineRect = GUILayoutUtility.GetRect(1, EditorGUIUtility.singleLineHeight); var labelRect = new Rect(lineRect.x, lineRect.y, EditorGUIUtility.labelWidth - indentOffset, lineRect.height); var fieldRect = new Rect(labelRect.xMax, lineRect.y, lineRect.width - labelRect.width - buttonWidth * (showCopy ? 2 : 1), lineRect.height); var buttonNewRect = new Rect(fieldRect.xMax, lineRect.y, buttonWidth, lineRect.height); var buttonCopyRect = new Rect(buttonNewRect.xMax, lineRect.y, buttonWidth, lineRect.height); EditorGUI.PrefixLabel(labelRect, EditorUtilities.GetContent("Profile|A reference to a profile asset.")); using (var scope = new EditorGUI.ChangeCheckScope()) { m_Profile.objectReferenceValue = (PostProcessProfile)EditorGUI.ObjectField(fieldRect, m_Profile.objectReferenceValue, typeof(PostProcessProfile), false); assetHasChanged = scope.changed; } if (GUI.Button(buttonNewRect, EditorUtilities.GetContent("New|Create a new profile."), showCopy ? EditorStyles.miniButtonLeft : EditorStyles.miniButton)) { // By default, try to put assets in a folder next to the currently active // scene file. If the user isn't a scene, put them in root instead. var targetName = m_Target.name; var scene = m_Target.gameObject.scene; var path = string.Empty; if (string.IsNullOrEmpty(scene.path)) { path = "Assets/"; } else { var scenePath = Path.GetDirectoryName(scene.path); var extPath = scene.name + "_Profiles"; var profilePath = scenePath + "/" + extPath; if (!AssetDatabase.IsValidFolder(profilePath)) { AssetDatabase.CreateFolder(scenePath, extPath); } path = profilePath + "/"; } path += targetName + " Profile.asset"; path = AssetDatabase.GenerateUniqueAssetPath(path); var asset = CreateInstance <PostProcessProfile>(); AssetDatabase.CreateAsset(asset, path); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); m_Profile.objectReferenceValue = asset; assetHasChanged = true; } if (showCopy && GUI.Button(buttonCopyRect, EditorUtilities.GetContent("Clone|Create a new profile and copy the content of the currently assigned profile."), EditorStyles.miniButtonRight)) { // Duplicate the currently assigned profile and save it as a new profile var origin = (PostProcessProfile)m_Profile.objectReferenceValue; var path = AssetDatabase.GetAssetPath(origin); path = AssetDatabase.GenerateUniqueAssetPath(path); var asset = Instantiate(origin); asset.settings.Clear(); foreach (var item in origin.settings) { var itemCopy = Instantiate(item); asset.settings.Add(itemCopy); } AssetDatabase.CreateAsset(asset, path); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); m_Profile.objectReferenceValue = asset; assetHasChanged = true; } EditorGUILayout.Space(); if (m_Profile.objectReferenceValue == null) { if (assetHasChanged) { m_EffectList.Clear(); // Asset wasn't null before, do some cleanup } EditorGUILayout.HelpBox("Assign a Post-process Profile to this volume using the \"Asset\" field or create one automatically by clicking the \"New\" button.\nAssets are automatically put in a folder next to your scene file. If you scene hasn't been saved yet they will be created at the root of the Assets folder.", MessageType.Info); } else { if (assetHasChanged) { RefreshEffectListEditor((PostProcessProfile)m_Profile.objectReferenceValue); } m_EffectList.OnGUI(); } serializedObject.ApplyModifiedProperties(); }
public override void OnInspectorGUI() { serializedObject.Update(); if (m_Target.isDirty) { RefreshEditors(); m_Target.isDirty = false; } EditorGUILayout.PropertyField(m_IsGlobal); if (!m_IsGlobal.boolValue) // Blend radius is not needed for global volumes { EditorGUILayout.PropertyField(m_BlendRadius); } EditorGUILayout.PropertyField(m_Priority); EditorGUILayout.Space(); using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField(EditorUtilities.GetContent("Overrides"), EditorStyles.boldLabel); if (GUILayout.Button("Add effect...", EditorStyles.miniButton)) { var menu = new GenericMenu(); var typeMap = PostProcessVolumeManager.instance.settingsTypes; foreach (var kvp in typeMap) { var type = kvp.Key; var title = EditorUtilities.GetContent(kvp.Value.menuItem); bool exists = m_Target.HasSettings(type); if (!exists) { menu.AddItem(title, false, () => AddEffectOverride(type)); } else { menu.AddDisabledItem(title); } } menu.ShowAsContext(); } } // Override list for (int i = 0; i < m_Editors.Count; i++) { var editor = m_Editors[i]; string title = editor.GetDisplayTitle(); int id = i; // Needed for closure capture below EditorUtilities.DrawSplitter(); bool displayContent = EditorUtilities.DrawHeader( title, editor.baseProperty, editor.activeProperty, () => ResetEffectOverride(editor.target.GetType(), id), () => RemoveEffectOverride(id) ); if (displayContent) { using (new EditorGUI.DisabledScope(!editor.activeProperty.boolValue)) editor.OnInternalInspectorGUI(); } } if (m_Editors.Count > 0) { EditorUtilities.DrawSplitter(); EditorGUILayout.Space(); } serializedObject.ApplyModifiedProperties(); }
public void OnGUI() { if (m_Asset.isDirty) { RefreshEditors(); m_Asset.isDirty = false; } EditorGUILayout.LabelField(EditorUtilities.GetContent("Overrides"), EditorStyles.boldLabel); // Override list for (int i = 0; i < m_Editors.Count; i++) { var editor = m_Editors[i]; string title = editor.GetDisplayTitle(); int id = i; // Needed for closure capture below EditorUtilities.DrawSplitter(); bool displayContent = EditorUtilities.DrawHeader( title, editor.baseProperty, editor.activeProperty, editor.target, () => ResetEffectOverride(editor.target.GetType(), id), () => RemoveEffectOverride(id) ); if (displayContent) { using (new EditorGUI.DisabledScope(!editor.activeProperty.boolValue)) editor.OnInternalInspectorGUI(); } } if (m_Editors.Count > 0) { EditorUtilities.DrawSplitter(); EditorGUILayout.Space(); } else { EditorGUILayout.HelpBox("No override set on this volume.", MessageType.Info); } if (GUILayout.Button("Add effect...", EditorStyles.miniButton)) { var menu = new GenericMenu(); var typeMap = PostProcessManager.instance.settingsTypes; foreach (var kvp in typeMap) { var type = kvp.Key; var title = EditorUtilities.GetContent(kvp.Value.menuItem); bool exists = m_Asset.HasSettings(type); if (!exists) { menu.AddItem(title, false, () => AddEffectOverride(type)); } else { menu.AddDisabledItem(title); } } menu.ShowAsContext(); } EditorGUILayout.Space(); }
public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.LabelField(EditorUtilities.GetContent("Volume blending"), EditorStyles.boldLabel); EditorGUI.indentLevel++; { using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.PrefixLabel("Trigger"); EditorGUI.indentLevel--; // The editor adds an indentation after the prefix label, this removes it using (new EditorGUILayout.HorizontalScope()) { m_VolumeTrigger.objectReferenceValue = (Transform)EditorGUILayout.ObjectField(m_VolumeTrigger.objectReferenceValue, typeof(Transform), false); if (GUILayout.Button(EditorUtilities.GetContent("This|Assigns the current GameObject as a trigger."), EditorStyles.miniButton)) { m_VolumeTrigger.objectReferenceValue = m_Target.transform; } } EditorGUI.indentLevel++; } EditorGUILayout.PropertyField(m_VolumeLayer, EditorUtilities.GetContent("Layer")); int mask = m_VolumeLayer.intValue; if (mask == 0) { EditorGUILayout.HelpBox("No layer has been set, the trigger will never be affected by volumes.", MessageType.Info); } else if (mask == -1 || ((mask & 1) != 0)) { EditorGUILayout.HelpBox("Do not use \"Everything\" or \"Default\" as a layer mask as it will slow down the volume blending process! Put post-processing volumes in their own dedicated layer for best performances.", MessageType.Warning); } } EditorGUI.indentLevel--; EditorGUILayout.Space(); EditorGUILayout.LabelField(EditorUtilities.GetContent("Anti-aliasing"), EditorStyles.boldLabel); { EditorGUI.indentLevel++; m_AntialiasingMode.intValue = EditorGUILayout.Popup("Mode", m_AntialiasingMode.intValue, s_AntialiasingMethodNames); if (m_AntialiasingMode.intValue == (int)PostProcessLayer.Antialiasing.TemporalAntialiasing) { EditorGUILayout.PropertyField(m_TaaJitterSpread); EditorGUILayout.PropertyField(m_TaaStationaryBlending); EditorGUILayout.PropertyField(m_TaaMotionBlending); EditorGUILayout.PropertyField(m_TaaSharpen); } } EditorGUI.indentLevel--; EditorGUILayout.Space(); EditorGUILayout.PropertyField(m_ShowDebugUI); if (m_ShowDebugUI.boolValue) { EditorGUI.indentLevel++; { EditorGUILayout.PropertyField(m_DebugMonitor); EditorGUILayout.HelpBox("The debug UI only works on compute-shader enabled platforms.", MessageType.Info); EditorGUILayout.HelpBox("Currently non-implemented.", MessageType.Warning); } EditorGUI.indentLevel--; } serializedObject.ApplyModifiedProperties(); }