| using UnityEngine; | 
| using UnityEngine.PostProcessing; | 
| using System; | 
| using System.Collections.Generic; | 
| using System.Linq.Expressions; | 
|   | 
| namespace UnityEditor.PostProcessing | 
| { | 
|     using Settings = ColorGradingModel.Settings; | 
|     using Tonemapper = ColorGradingModel.Tonemapper; | 
|     using ColorWheelMode = ColorGradingModel.ColorWheelMode; | 
|   | 
|     [PostProcessingModelEditor(typeof(ColorGradingModel))] | 
|     public class ColorGradingModelEditor : PostProcessingModelEditor | 
|     { | 
|         static GUIContent[] s_Tonemappers = | 
|         { | 
|             new GUIContent("None"), | 
|             new GUIContent("Filmic (ACES)"), | 
|             new GUIContent("Neutral") | 
|         }; | 
|   | 
|         struct TonemappingSettings | 
|         { | 
|             public SerializedProperty tonemapper; | 
|             public SerializedProperty neutralBlackIn; | 
|             public SerializedProperty neutralWhiteIn; | 
|             public SerializedProperty neutralBlackOut; | 
|             public SerializedProperty neutralWhiteOut; | 
|             public SerializedProperty neutralWhiteLevel; | 
|             public SerializedProperty neutralWhiteClip; | 
|         } | 
|   | 
|         struct BasicSettings | 
|         { | 
|             public SerializedProperty exposure; | 
|             public SerializedProperty temperature; | 
|             public SerializedProperty tint; | 
|             public SerializedProperty hueShift; | 
|             public SerializedProperty saturation; | 
|             public SerializedProperty contrast; | 
|         } | 
|   | 
|         struct ChannelMixerSettings | 
|         { | 
|             public SerializedProperty[] channels; | 
|             public SerializedProperty currentEditingChannel; | 
|         } | 
|   | 
|         struct ColorWheelsSettings | 
|         { | 
|             public SerializedProperty mode; | 
|             public SerializedProperty log; | 
|             public SerializedProperty linear; | 
|         } | 
|   | 
|         static GUIContent[] s_Curves = | 
|         { | 
|             new GUIContent("YRGB"), | 
|             new GUIContent("Hue VS Hue"), | 
|             new GUIContent("Hue VS Sat"), | 
|             new GUIContent("Sat VS Sat"), | 
|             new GUIContent("Lum VS Sat") | 
|         }; | 
|   | 
|         struct CurvesSettings | 
|         { | 
|             public SerializedProperty master; | 
|             public SerializedProperty red; | 
|             public SerializedProperty green; | 
|             public SerializedProperty blue; | 
|   | 
|             public SerializedProperty hueVShue; | 
|             public SerializedProperty hueVSsat; | 
|             public SerializedProperty satVSsat; | 
|             public SerializedProperty lumVSsat; | 
|   | 
|             public SerializedProperty currentEditingCurve; | 
|             public SerializedProperty curveY; | 
|             public SerializedProperty curveR; | 
|             public SerializedProperty curveG; | 
|             public SerializedProperty curveB; | 
|         } | 
|   | 
|         TonemappingSettings m_Tonemapping; | 
|         BasicSettings m_Basic; | 
|         ChannelMixerSettings m_ChannelMixer; | 
|         ColorWheelsSettings m_ColorWheels; | 
|         CurvesSettings m_Curves; | 
|   | 
|         CurveEditor m_CurveEditor; | 
|         Dictionary<SerializedProperty, Color> m_CurveDict; | 
|   | 
|         // Neutral tonemapping curve helper | 
|         const int k_CurveResolution = 24; | 
|         const float k_NeutralRangeX = 2f; | 
|         const float k_NeutralRangeY = 1f; | 
|         Vector3[] m_RectVertices = new Vector3[4]; | 
|         Vector3[] m_LineVertices = new Vector3[2]; | 
|         Vector3[] m_CurveVertices = new Vector3[k_CurveResolution]; | 
|         Rect m_NeutralCurveRect; | 
|   | 
|         public override void OnEnable() | 
|         { | 
|             // Tonemapping settings | 
|             m_Tonemapping = new TonemappingSettings | 
|             { | 
|                 tonemapper = FindSetting((Settings x) => x.tonemapping.tonemapper), | 
|                 neutralBlackIn = FindSetting((Settings x) => x.tonemapping.neutralBlackIn), | 
|                 neutralWhiteIn = FindSetting((Settings x) => x.tonemapping.neutralWhiteIn), | 
|                 neutralBlackOut = FindSetting((Settings x) => x.tonemapping.neutralBlackOut), | 
|                 neutralWhiteOut = FindSetting((Settings x) => x.tonemapping.neutralWhiteOut), | 
|                 neutralWhiteLevel = FindSetting((Settings x) => x.tonemapping.neutralWhiteLevel), | 
|                 neutralWhiteClip = FindSetting((Settings x) => x.tonemapping.neutralWhiteClip) | 
|             }; | 
|   | 
|             // Basic settings | 
|             m_Basic = new BasicSettings | 
|             { | 
|                 exposure = FindSetting((Settings x) => x.basic.postExposure), | 
|                 temperature = FindSetting((Settings x) => x.basic.temperature), | 
|                 tint = FindSetting((Settings x) => x.basic.tint), | 
|                 hueShift = FindSetting((Settings x) => x.basic.hueShift), | 
|                 saturation = FindSetting((Settings x) => x.basic.saturation), | 
|                 contrast = FindSetting((Settings x) => x.basic.contrast) | 
|             }; | 
|   | 
|             // Channel mixer | 
|             m_ChannelMixer = new ChannelMixerSettings | 
|             { | 
|                 channels = new[] | 
|                 { | 
|                     FindSetting((Settings x) => x.channelMixer.red), | 
|                     FindSetting((Settings x) => x.channelMixer.green), | 
|                     FindSetting((Settings x) => x.channelMixer.blue) | 
|                 }, | 
|                 currentEditingChannel = FindSetting((Settings x) => x.channelMixer.currentEditingChannel) | 
|             }; | 
|   | 
|             // Color wheels | 
|             m_ColorWheels = new ColorWheelsSettings | 
|             { | 
|                 mode = FindSetting((Settings x) => x.colorWheels.mode), | 
|                 log = FindSetting((Settings x) => x.colorWheels.log), | 
|                 linear = FindSetting((Settings x) => x.colorWheels.linear) | 
|             }; | 
|   | 
|             // Curves | 
|             m_Curves = new CurvesSettings | 
|             { | 
|                 master = FindSetting((Settings x) => x.curves.master.curve), | 
|                 red = FindSetting((Settings x) => x.curves.red.curve), | 
|                 green = FindSetting((Settings x) => x.curves.green.curve), | 
|                 blue = FindSetting((Settings x) => x.curves.blue.curve), | 
|   | 
|                 hueVShue = FindSetting((Settings x) => x.curves.hueVShue.curve), | 
|                 hueVSsat = FindSetting((Settings x) => x.curves.hueVSsat.curve), | 
|                 satVSsat = FindSetting((Settings x) => x.curves.satVSsat.curve), | 
|                 lumVSsat = FindSetting((Settings x) => x.curves.lumVSsat.curve), | 
|   | 
|                 currentEditingCurve = FindSetting((Settings x) => x.curves.e_CurrentEditingCurve), | 
|                 curveY = FindSetting((Settings x) => x.curves.e_CurveY), | 
|                 curveR = FindSetting((Settings x) => x.curves.e_CurveR), | 
|                 curveG = FindSetting((Settings x) => x.curves.e_CurveG), | 
|                 curveB = FindSetting((Settings x) => x.curves.e_CurveB) | 
|             }; | 
|   | 
|             // Prepare the curve editor and extract curve display settings | 
|             m_CurveDict = new Dictionary<SerializedProperty, Color>(); | 
|   | 
|             var settings = CurveEditor.Settings.defaultSettings; | 
|   | 
|             m_CurveEditor = new CurveEditor(settings); | 
|             AddCurve(m_Curves.master,   new Color(1f, 1f, 1f), 2, false); | 
|             AddCurve(m_Curves.red,      new Color(1f, 0f, 0f), 2, false); | 
|             AddCurve(m_Curves.green,    new Color(0f, 1f, 0f), 2, false); | 
|             AddCurve(m_Curves.blue,     new Color(0f, 0.5f, 1f), 2, false); | 
|             AddCurve(m_Curves.hueVShue, new Color(1f, 1f, 1f), 0, true); | 
|             AddCurve(m_Curves.hueVSsat, new Color(1f, 1f, 1f), 0, true); | 
|             AddCurve(m_Curves.satVSsat, new Color(1f, 1f, 1f), 0, false); | 
|             AddCurve(m_Curves.lumVSsat, new Color(1f, 1f, 1f), 0, false); | 
|         } | 
|   | 
|         void AddCurve(SerializedProperty prop, Color color, uint minPointCount, bool loop) | 
|         { | 
|             var state = CurveEditor.CurveState.defaultState; | 
|             state.color = color; | 
|             state.visible = false; | 
|             state.minPointCount = minPointCount; | 
|             state.onlyShowHandlesOnSelection = true; | 
|             state.zeroKeyConstantValue = 0.5f; | 
|             state.loopInBounds = loop; | 
|             m_CurveEditor.Add(prop, state); | 
|             m_CurveDict.Add(prop, color); | 
|         } | 
|   | 
|         public override void OnDisable() | 
|         { | 
|             m_CurveEditor.RemoveAll(); | 
|         } | 
|   | 
|         public override void OnInspectorGUI() | 
|         { | 
|             DoGUIFor("Tonemapping", DoTonemappingGUI); | 
|             EditorGUILayout.Space(); | 
|             DoGUIFor("Basic", DoBasicGUI); | 
|             EditorGUILayout.Space(); | 
|             DoGUIFor("Channel Mixer", DoChannelMixerGUI); | 
|             EditorGUILayout.Space(); | 
|             DoGUIFor("Trackballs", DoColorWheelsGUI); | 
|             EditorGUILayout.Space(); | 
|             DoGUIFor("Grading Curves", DoCurvesGUI); | 
|         } | 
|   | 
|         void DoGUIFor(string title, Action func) | 
|         { | 
|             EditorGUILayout.LabelField(title, EditorStyles.boldLabel); | 
|             EditorGUI.indentLevel++; | 
|             func(); | 
|             EditorGUI.indentLevel--; | 
|         } | 
|   | 
|         void DoTonemappingGUI() | 
|         { | 
|             int tid = EditorGUILayout.Popup(EditorGUIHelper.GetContent("Tonemapper"), m_Tonemapping.tonemapper.intValue, s_Tonemappers); | 
|   | 
|             if (tid == (int)Tonemapper.Neutral) | 
|             { | 
|                 DrawNeutralTonemappingCurve(); | 
|   | 
|                 EditorGUILayout.PropertyField(m_Tonemapping.neutralBlackIn, EditorGUIHelper.GetContent("Black In")); | 
|                 EditorGUILayout.PropertyField(m_Tonemapping.neutralWhiteIn, EditorGUIHelper.GetContent("White In")); | 
|                 EditorGUILayout.PropertyField(m_Tonemapping.neutralBlackOut, EditorGUIHelper.GetContent("Black Out")); | 
|                 EditorGUILayout.PropertyField(m_Tonemapping.neutralWhiteOut, EditorGUIHelper.GetContent("White Out")); | 
|                 EditorGUILayout.PropertyField(m_Tonemapping.neutralWhiteLevel, EditorGUIHelper.GetContent("White Level")); | 
|                 EditorGUILayout.PropertyField(m_Tonemapping.neutralWhiteClip, EditorGUIHelper.GetContent("White Clip")); | 
|             } | 
|   | 
|             m_Tonemapping.tonemapper.intValue = tid; | 
|         } | 
|   | 
|         void DrawNeutralTonemappingCurve() | 
|         { | 
|             using (new GUILayout.HorizontalScope()) | 
|             { | 
|                 GUILayout.Space(EditorGUI.indentLevel * 15f); | 
|                 m_NeutralCurveRect = GUILayoutUtility.GetRect(128, 80); | 
|             } | 
|   | 
|             // Background | 
|             m_RectVertices[0] = PointInRect(             0f,              0f); | 
|             m_RectVertices[1] = PointInRect(k_NeutralRangeX,              0f); | 
|             m_RectVertices[2] = PointInRect(k_NeutralRangeX, k_NeutralRangeY); | 
|             m_RectVertices[3] = PointInRect(             0f, k_NeutralRangeY); | 
|   | 
|             Handles.DrawSolidRectangleWithOutline( | 
|                 m_RectVertices, | 
|                 Color.white * 0.1f, | 
|                 Color.white * 0.4f | 
|                 ); | 
|   | 
|             // Horizontal lines | 
|             for (var i = 1; i < k_NeutralRangeY; i++) | 
|                 DrawLine(0, i, k_NeutralRangeX, i, 0.4f); | 
|   | 
|             // Vertical lines | 
|             for (var i = 1; i < k_NeutralRangeX; i++) | 
|                 DrawLine(i, 0, i, k_NeutralRangeY, 0.4f); | 
|   | 
|             // Label | 
|             Handles.Label( | 
|                 PointInRect(0, k_NeutralRangeY) + Vector3.right, | 
|                 "Neutral Tonemapper", EditorStyles.miniLabel | 
|                 ); | 
|   | 
|             // Precompute some values | 
|             var tonemap = ((ColorGradingModel)target).settings.tonemapping; | 
|   | 
|             const float scaleFactor = 20f; | 
|             const float scaleFactorHalf = scaleFactor * 0.5f; | 
|   | 
|             float inBlack = tonemap.neutralBlackIn * scaleFactor + 1f; | 
|             float outBlack = tonemap.neutralBlackOut * scaleFactorHalf + 1f; | 
|             float inWhite = tonemap.neutralWhiteIn / scaleFactor; | 
|             float outWhite = 1f - tonemap.neutralWhiteOut / scaleFactor; | 
|             float blackRatio = inBlack / outBlack; | 
|             float whiteRatio = inWhite / outWhite; | 
|   | 
|             const float a = 0.2f; | 
|             float b = Mathf.Max(0f, Mathf.LerpUnclamped(0.57f, 0.37f, blackRatio)); | 
|             float c = Mathf.LerpUnclamped(0.01f, 0.24f, whiteRatio); | 
|             float d = Mathf.Max(0f, Mathf.LerpUnclamped(0.02f, 0.20f, blackRatio)); | 
|             const float e = 0.02f; | 
|             const float f = 0.30f; | 
|             float whiteLevel = tonemap.neutralWhiteLevel; | 
|             float whiteClip = tonemap.neutralWhiteClip / scaleFactorHalf; | 
|   | 
|             // Tonemapping curve | 
|             var vcount = 0; | 
|             while (vcount < k_CurveResolution) | 
|             { | 
|                 float x = k_NeutralRangeX * vcount / (k_CurveResolution - 1); | 
|                 float y = NeutralTonemap(x, a, b, c, d, e, f, whiteLevel, whiteClip); | 
|   | 
|                 if (y < k_NeutralRangeY) | 
|                 { | 
|                     m_CurveVertices[vcount++] = PointInRect(x, y); | 
|                 } | 
|                 else | 
|                 { | 
|                     if (vcount > 1) | 
|                     { | 
|                         // Extend the last segment to the top edge of the rect. | 
|                         var v1 = m_CurveVertices[vcount - 2]; | 
|                         var v2 = m_CurveVertices[vcount - 1]; | 
|                         var clip = (m_NeutralCurveRect.y - v1.y) / (v2.y - v1.y); | 
|                         m_CurveVertices[vcount - 1] = v1 + (v2 - v1) * clip; | 
|                     } | 
|                     break; | 
|                 } | 
|             } | 
|   | 
|             if (vcount > 1) | 
|             { | 
|                 Handles.color = Color.white * 0.9f; | 
|                 Handles.DrawAAPolyLine(2.0f, vcount, m_CurveVertices); | 
|             } | 
|         } | 
|   | 
|         void DrawLine(float x1, float y1, float x2, float y2, float grayscale) | 
|         { | 
|             m_LineVertices[0] = PointInRect(x1, y1); | 
|             m_LineVertices[1] = PointInRect(x2, y2); | 
|             Handles.color = Color.white * grayscale; | 
|             Handles.DrawAAPolyLine(2f, m_LineVertices); | 
|         } | 
|   | 
|         Vector3 PointInRect(float x, float y) | 
|         { | 
|             x = Mathf.Lerp(m_NeutralCurveRect.x, m_NeutralCurveRect.xMax, x / k_NeutralRangeX); | 
|             y = Mathf.Lerp(m_NeutralCurveRect.yMax, m_NeutralCurveRect.y, y / k_NeutralRangeY); | 
|             return new Vector3(x, y, 0); | 
|         } | 
|   | 
|         float NeutralCurve(float x, float a, float b, float c, float d, float e, float f) | 
|         { | 
|             return ((x * (a * x + c * b) + d * e) / (x * (a * x + b) + d * f)) - e / f; | 
|         } | 
|   | 
|         float NeutralTonemap(float x, float a, float b, float c, float d, float e, float f, float whiteLevel, float whiteClip) | 
|         { | 
|             x = Mathf.Max(0f, x); | 
|   | 
|             // Tonemap | 
|             float whiteScale = 1f / NeutralCurve(whiteLevel, a, b, c, d, e, f); | 
|             x = NeutralCurve(x * whiteScale, a, b, c, d, e, f); | 
|             x *= whiteScale; | 
|   | 
|             // Post-curve white point adjustment | 
|             x /= whiteClip; | 
|   | 
|             return x; | 
|         } | 
|   | 
|         void DoBasicGUI() | 
|         { | 
|             EditorGUILayout.PropertyField(m_Basic.exposure, EditorGUIHelper.GetContent("Post Exposure (EV)")); | 
|             EditorGUILayout.PropertyField(m_Basic.temperature); | 
|             EditorGUILayout.PropertyField(m_Basic.tint); | 
|             EditorGUILayout.PropertyField(m_Basic.hueShift); | 
|             EditorGUILayout.PropertyField(m_Basic.saturation); | 
|             EditorGUILayout.PropertyField(m_Basic.contrast); | 
|         } | 
|   | 
|         void DoChannelMixerGUI() | 
|         { | 
|             int currentChannel = m_ChannelMixer.currentEditingChannel.intValue; | 
|   | 
|             EditorGUI.BeginChangeCheck(); | 
|             { | 
|                 using (new EditorGUILayout.HorizontalScope()) | 
|                 { | 
|                     EditorGUILayout.PrefixLabel("Channel"); | 
|                     if (GUILayout.Toggle(currentChannel == 0, EditorGUIHelper.GetContent("Red|Red output channel."), EditorStyles.miniButtonLeft)) currentChannel = 0; | 
|                     if (GUILayout.Toggle(currentChannel == 1, EditorGUIHelper.GetContent("Green|Green output channel."), EditorStyles.miniButtonMid)) currentChannel = 1; | 
|                     if (GUILayout.Toggle(currentChannel == 2, EditorGUIHelper.GetContent("Blue|Blue output channel."), EditorStyles.miniButtonRight)) currentChannel = 2; | 
|                 } | 
|             } | 
|             if (EditorGUI.EndChangeCheck()) | 
|             { | 
|                 GUI.FocusControl(null); | 
|             } | 
|   | 
|             var serializedChannel = m_ChannelMixer.channels[currentChannel]; | 
|             m_ChannelMixer.currentEditingChannel.intValue = currentChannel; | 
|   | 
|             var v = serializedChannel.vector3Value; | 
|             v.x = EditorGUILayout.Slider(EditorGUIHelper.GetContent("Red|Modify influence of the red channel within the overall mix."), v.x, -2f, 2f); | 
|             v.y = EditorGUILayout.Slider(EditorGUIHelper.GetContent("Green|Modify influence of the green channel within the overall mix."), v.y, -2f, 2f); | 
|             v.z = EditorGUILayout.Slider(EditorGUIHelper.GetContent("Blue|Modify influence of the blue channel within the overall mix."), v.z, -2f, 2f); | 
|             serializedChannel.vector3Value = v; | 
|         } | 
|   | 
|         void DoColorWheelsGUI() | 
|         { | 
|             int wheelMode = m_ColorWheels.mode.intValue; | 
|   | 
|             using (new EditorGUILayout.HorizontalScope()) | 
|             { | 
|                 GUILayout.Space(15); | 
|                 if (GUILayout.Toggle(wheelMode == (int)ColorWheelMode.Linear, "Linear", EditorStyles.miniButtonLeft)) wheelMode = (int)ColorWheelMode.Linear; | 
|                 if (GUILayout.Toggle(wheelMode == (int)ColorWheelMode.Log, "Log", EditorStyles.miniButtonRight)) wheelMode = (int)ColorWheelMode.Log; | 
|             } | 
|   | 
|             m_ColorWheels.mode.intValue = wheelMode; | 
|             EditorGUILayout.Space(); | 
|   | 
|             if (wheelMode == (int)ColorWheelMode.Linear) | 
|             { | 
|                 EditorGUILayout.PropertyField(m_ColorWheels.linear); | 
|                 WheelSetTitle(GUILayoutUtility.GetLastRect(), "Linear Controls"); | 
|             } | 
|             else if (wheelMode == (int)ColorWheelMode.Log) | 
|             { | 
|                 EditorGUILayout.PropertyField(m_ColorWheels.log); | 
|                 WheelSetTitle(GUILayoutUtility.GetLastRect(), "Log Controls"); | 
|             } | 
|         } | 
|   | 
|         static void WheelSetTitle(Rect position, string label) | 
|         { | 
|             var matrix = GUI.matrix; | 
|             var rect = new Rect(position.x - 10f, position.y, TrackballGroupDrawer.m_Size, TrackballGroupDrawer.m_Size); | 
|             GUIUtility.RotateAroundPivot(-90f, rect.center); | 
|             GUI.Label(rect, label, FxStyles.centeredMiniLabel); | 
|             GUI.matrix = matrix; | 
|         } | 
|   | 
|         void ResetVisibleCurves() | 
|         { | 
|             foreach (var curve in m_CurveDict) | 
|             { | 
|                 var state = m_CurveEditor.GetCurveState(curve.Key); | 
|                 state.visible = false; | 
|                 m_CurveEditor.SetCurveState(curve.Key, state); | 
|             } | 
|         } | 
|   | 
|         void SetCurveVisible(SerializedProperty prop) | 
|         { | 
|             var state = m_CurveEditor.GetCurveState(prop); | 
|             state.visible = true; | 
|             m_CurveEditor.SetCurveState(prop, state); | 
|         } | 
|   | 
|         bool SpecialToggle(bool value, string name, out bool rightClicked) | 
|         { | 
|             var rect = GUILayoutUtility.GetRect(EditorGUIHelper.GetContent(name), EditorStyles.toolbarButton); | 
|   | 
|             var e = Event.current; | 
|             rightClicked = (e.type == EventType.MouseUp && rect.Contains(e.mousePosition) && e.button == 1); | 
|   | 
|             return GUI.Toggle(rect, value, name, EditorStyles.toolbarButton); | 
|         } | 
|   | 
|         static Material s_MaterialSpline; | 
|   | 
|         void DoCurvesGUI() | 
|         { | 
|             EditorGUILayout.Space(); | 
|             EditorGUI.indentLevel -= 2; | 
|             ResetVisibleCurves(); | 
|   | 
|             using (new EditorGUI.DisabledGroupScope(serializedProperty.serializedObject.isEditingMultipleObjects)) | 
|             { | 
|                 int curveEditingId = 0; | 
|   | 
|                 // Top toolbar | 
|                 using (new GUILayout.HorizontalScope(EditorStyles.toolbar)) | 
|                 { | 
|                     curveEditingId = EditorGUILayout.Popup(m_Curves.currentEditingCurve.intValue, s_Curves, EditorStyles.toolbarPopup, GUILayout.MaxWidth(150f)); | 
|                     bool y = false, r = false, g = false, b = false; | 
|   | 
|                     if (curveEditingId == 0) | 
|                     { | 
|                         EditorGUILayout.Space(); | 
|   | 
|                         bool rightClickedY, rightClickedR, rightClickedG, rightClickedB; | 
|   | 
|                         y = SpecialToggle(m_Curves.curveY.boolValue, "Y", out rightClickedY); | 
|                         r = SpecialToggle(m_Curves.curveR.boolValue, "R", out rightClickedR); | 
|                         g = SpecialToggle(m_Curves.curveG.boolValue, "G", out rightClickedG); | 
|                         b = SpecialToggle(m_Curves.curveB.boolValue, "B", out rightClickedB); | 
|   | 
|                         if (!y && !r && !g && !b) | 
|                         { | 
|                             r = g = b = false; | 
|                             y = true; | 
|                         } | 
|   | 
|                         if (rightClickedY || rightClickedR || rightClickedG || rightClickedB) | 
|                         { | 
|                             y = rightClickedY; | 
|                             r = rightClickedR; | 
|                             g = rightClickedG; | 
|                             b = rightClickedB; | 
|                         } | 
|   | 
|                         if (y) SetCurveVisible(m_Curves.master); | 
|                         if (r) SetCurveVisible(m_Curves.red); | 
|                         if (g) SetCurveVisible(m_Curves.green); | 
|                         if (b) SetCurveVisible(m_Curves.blue); | 
|   | 
|                         m_Curves.curveY.boolValue = y; | 
|                         m_Curves.curveR.boolValue = r; | 
|                         m_Curves.curveG.boolValue = g; | 
|                         m_Curves.curveB.boolValue = b; | 
|                     } | 
|                     else | 
|                     { | 
|                         switch (curveEditingId) | 
|                         { | 
|                             case 1: SetCurveVisible(m_Curves.hueVShue); | 
|                                 break; | 
|                             case 2: SetCurveVisible(m_Curves.hueVSsat); | 
|                                 break; | 
|                             case 3: SetCurveVisible(m_Curves.satVSsat); | 
|                                 break; | 
|                             case 4: SetCurveVisible(m_Curves.lumVSsat); | 
|                                 break; | 
|                         } | 
|                     } | 
|   | 
|                     GUILayout.FlexibleSpace(); | 
|   | 
|                     if (GUILayout.Button("Reset", EditorStyles.toolbarButton)) | 
|                     { | 
|                         switch (curveEditingId) | 
|                         { | 
|                             case 0: | 
|                                 if (y) m_Curves.master.animationCurveValue = AnimationCurve.Linear(0f, 0f, 1f, 1f); | 
|                                 if (r) m_Curves.red.animationCurveValue    = AnimationCurve.Linear(0f, 0f, 1f, 1f); | 
|                                 if (g) m_Curves.green.animationCurveValue  = AnimationCurve.Linear(0f, 0f, 1f, 1f); | 
|                                 if (b) m_Curves.blue.animationCurveValue   = AnimationCurve.Linear(0f, 0f, 1f, 1f); | 
|                                 break; | 
|                             case 1: m_Curves.hueVShue.animationCurveValue = new AnimationCurve(); | 
|                                 break; | 
|                             case 2: m_Curves.hueVSsat.animationCurveValue = new AnimationCurve(); | 
|                                 break; | 
|                             case 3: m_Curves.satVSsat.animationCurveValue = new AnimationCurve(); | 
|                                 break; | 
|                             case 4: m_Curves.lumVSsat.animationCurveValue = new AnimationCurve(); | 
|                                 break; | 
|                         } | 
|                     } | 
|   | 
|                     m_Curves.currentEditingCurve.intValue = curveEditingId; | 
|                 } | 
|   | 
|                 // Curve area | 
|                 var settings = m_CurveEditor.settings; | 
|                 var rect = GUILayoutUtility.GetAspectRect(2f); | 
|                 var innerRect = settings.padding.Remove(rect); | 
|   | 
|                 if (Event.current.type == EventType.Repaint) | 
|                 { | 
|                     // Background | 
|                     EditorGUI.DrawRect(rect, new Color(0.15f, 0.15f, 0.15f, 1f)); | 
|   | 
|                     if (s_MaterialSpline == null) | 
|                         s_MaterialSpline = new Material(Shader.Find("Hidden/Post FX/UI/Curve Background")) { hideFlags = HideFlags.HideAndDontSave }; | 
|   | 
|                     if (curveEditingId == 1 || curveEditingId == 2) | 
|                         DrawBackgroundTexture(innerRect, 0); | 
|                     else if (curveEditingId == 3 || curveEditingId == 4) | 
|                         DrawBackgroundTexture(innerRect, 1); | 
|   | 
|                     // Bounds | 
|                     Handles.color = Color.white; | 
|                     Handles.DrawSolidRectangleWithOutline(innerRect, Color.clear, new Color(0.8f, 0.8f, 0.8f, 0.5f)); | 
|   | 
|                     // Grid setup | 
|                     Handles.color = new Color(1f, 1f, 1f, 0.05f); | 
|                     int hLines = (int)Mathf.Sqrt(innerRect.width); | 
|                     int vLines = (int)(hLines / (innerRect.width / innerRect.height)); | 
|   | 
|                     // Vertical grid | 
|                     int gridOffset = Mathf.FloorToInt(innerRect.width / hLines); | 
|                     int gridPadding = ((int)(innerRect.width) % hLines) / 2; | 
|   | 
|                     for (int i = 1; i < hLines; i++) | 
|                     { | 
|                         var offset = i * Vector2.right * gridOffset; | 
|                         offset.x += gridPadding; | 
|                         Handles.DrawLine(innerRect.position + offset, new Vector2(innerRect.x, innerRect.yMax - 1) + offset); | 
|                     } | 
|   | 
|                     // Horizontal grid | 
|                     gridOffset = Mathf.FloorToInt(innerRect.height / vLines); | 
|                     gridPadding = ((int)(innerRect.height) % vLines) / 2; | 
|   | 
|                     for (int i = 1; i < vLines; i++) | 
|                     { | 
|                         var offset = i * Vector2.up * gridOffset; | 
|                         offset.y += gridPadding; | 
|                         Handles.DrawLine(innerRect.position + offset, new Vector2(innerRect.xMax - 1, innerRect.y) + offset); | 
|                     } | 
|                 } | 
|   | 
|                 // Curve editor | 
|                 if (m_CurveEditor.OnGUI(rect)) | 
|                 { | 
|                     Repaint(); | 
|                     GUI.changed = true; | 
|                 } | 
|   | 
|                 if (Event.current.type == EventType.Repaint) | 
|                 { | 
|                     // Borders | 
|                     Handles.color = Color.black; | 
|                     Handles.DrawLine(new Vector2(rect.x, rect.y - 18f), new Vector2(rect.xMax, rect.y - 18f)); | 
|                     Handles.DrawLine(new Vector2(rect.x, rect.y - 19f), new Vector2(rect.x, rect.yMax)); | 
|                     Handles.DrawLine(new Vector2(rect.x, rect.yMax), new Vector2(rect.xMax, rect.yMax)); | 
|                     Handles.DrawLine(new Vector2(rect.xMax, rect.yMax), new Vector2(rect.xMax, rect.y - 18f)); | 
|   | 
|                     // Selection info | 
|                     var selection = m_CurveEditor.GetSelection(); | 
|   | 
|                     if (selection.curve != null && selection.keyframeIndex > -1) | 
|                     { | 
|                         var key = selection.keyframe.Value; | 
|                         var infoRect = innerRect; | 
|                         infoRect.x += 5f; | 
|                         infoRect.width = 100f; | 
|                         infoRect.height = 30f; | 
|                         GUI.Label(infoRect, string.Format("{0}\n{1}", key.time.ToString("F3"), key.value.ToString("F3")), FxStyles.preLabel); | 
|                     } | 
|                 } | 
|             } | 
|   | 
|             /* | 
|             EditorGUILayout.HelpBox( | 
|                 @"Curve editor cheat sheet: | 
| - [Del] or [Backspace] to remove a key | 
| - [Ctrl] to break a tangent handle | 
| - [Shift] to align tangent handles | 
| - [Double click] to create a key on the curve(s) at mouse position | 
| - [Alt] + [Double click] to create a key on the curve(s) at a given time", | 
|                 MessageType.Info); | 
|             */ | 
|   | 
|             EditorGUILayout.Space(); | 
|             EditorGUI.indentLevel += 2; | 
|         } | 
|   | 
|         void DrawBackgroundTexture(Rect rect, int pass) | 
|         { | 
|             float scale = EditorGUIUtility.pixelsPerPoint; | 
|   | 
|             var oldRt = RenderTexture.active; | 
|             var rt = RenderTexture.GetTemporary(Mathf.CeilToInt(rect.width * scale), Mathf.CeilToInt(rect.height * scale), 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear); | 
|             s_MaterialSpline.SetFloat("_DisabledState", GUI.enabled ? 1f : 0.5f); | 
|             s_MaterialSpline.SetFloat("_PixelScaling", EditorGUIUtility.pixelsPerPoint); | 
|   | 
|             Graphics.Blit(null, rt, s_MaterialSpline, pass); | 
|             RenderTexture.active = oldRt; | 
|   | 
|             GUI.DrawTexture(rect, rt); | 
|             RenderTexture.ReleaseTemporary(rt); | 
|         } | 
|     } | 
| } |