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);
|
|
}
|
|
}
|
|
}
|