111
This commit is contained in:
847
Assets/ThirdParty/PostProcessing/Editor/Utils/CurveEditor.cs
vendored
Normal file
847
Assets/ThirdParty/PostProcessing/Editor/Utils/CurveEditor.cs
vendored
Normal file
@@ -0,0 +1,847 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.PostProcessing
|
||||
{
|
||||
public sealed class CurveEditor
|
||||
{
|
||||
#region Enums
|
||||
|
||||
enum EditMode
|
||||
{
|
||||
None,
|
||||
Moving,
|
||||
TangentEdit
|
||||
}
|
||||
|
||||
enum Tangent
|
||||
{
|
||||
In,
|
||||
Out
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Structs
|
||||
public struct Settings
|
||||
{
|
||||
public Rect bounds;
|
||||
public RectOffset padding;
|
||||
public Color selectionColor;
|
||||
public float curvePickingDistance;
|
||||
public float keyTimeClampingDistance;
|
||||
|
||||
public static Settings defaultSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Settings
|
||||
{
|
||||
bounds = new Rect(0f, 0f, 1f, 1f),
|
||||
padding = new RectOffset(10, 10, 10, 10),
|
||||
selectionColor = Color.yellow,
|
||||
curvePickingDistance = 6f,
|
||||
keyTimeClampingDistance = 1e-4f
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct CurveState
|
||||
{
|
||||
public bool visible;
|
||||
public bool editable;
|
||||
public uint minPointCount;
|
||||
public float zeroKeyConstantValue;
|
||||
public Color color;
|
||||
public float width;
|
||||
public float handleWidth;
|
||||
public bool showNonEditableHandles;
|
||||
public bool onlyShowHandlesOnSelection;
|
||||
public bool loopInBounds;
|
||||
|
||||
public static CurveState defaultState
|
||||
{
|
||||
get
|
||||
{
|
||||
return new CurveState
|
||||
{
|
||||
visible = true,
|
||||
editable = true,
|
||||
minPointCount = 2,
|
||||
zeroKeyConstantValue = 0f,
|
||||
color = Color.white,
|
||||
width = 2f,
|
||||
handleWidth = 2f,
|
||||
showNonEditableHandles = true,
|
||||
onlyShowHandlesOnSelection = false,
|
||||
loopInBounds = false
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct Selection
|
||||
{
|
||||
public SerializedProperty curve;
|
||||
public int keyframeIndex;
|
||||
public Keyframe? keyframe;
|
||||
|
||||
public Selection(SerializedProperty curve, int keyframeIndex, Keyframe? keyframe)
|
||||
{
|
||||
this.curve = curve;
|
||||
this.keyframeIndex = keyframeIndex;
|
||||
this.keyframe = keyframe;
|
||||
}
|
||||
}
|
||||
|
||||
internal struct MenuAction
|
||||
{
|
||||
internal SerializedProperty curve;
|
||||
internal int index;
|
||||
internal Vector3 position;
|
||||
|
||||
internal MenuAction(SerializedProperty curve)
|
||||
{
|
||||
this.curve = curve;
|
||||
this.index = -1;
|
||||
this.position = Vector3.zero;
|
||||
}
|
||||
|
||||
internal MenuAction(SerializedProperty curve, int index)
|
||||
{
|
||||
this.curve = curve;
|
||||
this.index = index;
|
||||
this.position = Vector3.zero;
|
||||
}
|
||||
|
||||
internal MenuAction(SerializedProperty curve, Vector3 position)
|
||||
{
|
||||
this.curve = curve;
|
||||
this.index = -1;
|
||||
this.position = position;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Fields & properties
|
||||
public Settings settings { get; private set; }
|
||||
|
||||
Dictionary<SerializedProperty, CurveState> m_Curves;
|
||||
Rect m_CurveArea;
|
||||
|
||||
SerializedProperty m_SelectedCurve;
|
||||
int m_SelectedKeyframeIndex = -1;
|
||||
|
||||
EditMode m_EditMode = EditMode.None;
|
||||
Tangent m_TangentEditMode;
|
||||
|
||||
bool m_Dirty;
|
||||
#endregion
|
||||
|
||||
#region Constructors & destructors
|
||||
public CurveEditor()
|
||||
: this(Settings.defaultSettings)
|
||||
{}
|
||||
|
||||
public CurveEditor(Settings settings)
|
||||
{
|
||||
this.settings = settings;
|
||||
m_Curves = new Dictionary<SerializedProperty, CurveState>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public API
|
||||
public void Add(params SerializedProperty[] curves)
|
||||
{
|
||||
foreach (var curve in curves)
|
||||
Add(curve, CurveState.defaultState);
|
||||
}
|
||||
|
||||
public void Add(SerializedProperty curve)
|
||||
{
|
||||
Add(curve, CurveState.defaultState);
|
||||
}
|
||||
|
||||
public void Add(SerializedProperty curve, CurveState state)
|
||||
{
|
||||
// Make sure the property is in fact an AnimationCurve
|
||||
var animCurve = curve.animationCurveValue;
|
||||
if (animCurve == null)
|
||||
throw new ArgumentException("curve");
|
||||
|
||||
if (m_Curves.ContainsKey(curve))
|
||||
Debug.LogWarning("Curve has already been added to the editor");
|
||||
|
||||
m_Curves.Add(curve, state);
|
||||
}
|
||||
|
||||
public void Remove(SerializedProperty curve)
|
||||
{
|
||||
m_Curves.Remove(curve);
|
||||
}
|
||||
|
||||
public void RemoveAll()
|
||||
{
|
||||
m_Curves.Clear();
|
||||
}
|
||||
|
||||
public CurveState GetCurveState(SerializedProperty curve)
|
||||
{
|
||||
CurveState state;
|
||||
if (!m_Curves.TryGetValue(curve, out state))
|
||||
throw new KeyNotFoundException("curve");
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
public void SetCurveState(SerializedProperty curve, CurveState state)
|
||||
{
|
||||
if (!m_Curves.ContainsKey(curve))
|
||||
throw new KeyNotFoundException("curve");
|
||||
|
||||
m_Curves[curve] = state;
|
||||
}
|
||||
|
||||
public Selection GetSelection()
|
||||
{
|
||||
Keyframe? key = null;
|
||||
if (m_SelectedKeyframeIndex > -1)
|
||||
{
|
||||
var curve = m_SelectedCurve.animationCurveValue;
|
||||
|
||||
if (m_SelectedKeyframeIndex >= curve.length)
|
||||
m_SelectedKeyframeIndex = -1;
|
||||
else
|
||||
key = curve[m_SelectedKeyframeIndex];
|
||||
}
|
||||
|
||||
return new Selection(m_SelectedCurve, m_SelectedKeyframeIndex, key);
|
||||
}
|
||||
|
||||
public void SetKeyframe(SerializedProperty curve, int keyframeIndex, Keyframe keyframe)
|
||||
{
|
||||
var animCurve = curve.animationCurveValue;
|
||||
SetKeyframe(animCurve, keyframeIndex, keyframe);
|
||||
SaveCurve(curve, animCurve);
|
||||
}
|
||||
|
||||
public bool OnGUI(Rect rect)
|
||||
{
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
m_Dirty = false;
|
||||
|
||||
GUI.BeginClip(rect);
|
||||
{
|
||||
var area = new Rect(Vector2.zero, rect.size);
|
||||
m_CurveArea = settings.padding.Remove(area);
|
||||
|
||||
foreach (var curve in m_Curves)
|
||||
OnCurveGUI(area, curve.Key, curve.Value);
|
||||
|
||||
OnGeneralUI(area);
|
||||
}
|
||||
GUI.EndClip();
|
||||
|
||||
return m_Dirty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI & events
|
||||
|
||||
void OnCurveGUI(Rect rect, SerializedProperty curve, CurveState state)
|
||||
{
|
||||
// Discard invisible curves
|
||||
if (!state.visible)
|
||||
return;
|
||||
|
||||
var animCurve = curve.animationCurveValue;
|
||||
var keys = animCurve.keys;
|
||||
var length = keys.Length;
|
||||
|
||||
// Curve drawing
|
||||
// Slightly dim non-editable curves
|
||||
var color = state.color;
|
||||
if (!state.editable)
|
||||
color.a *= 0.5f;
|
||||
|
||||
Handles.color = color;
|
||||
var bounds = settings.bounds;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
var p1 = CurveToCanvas(new Vector3(bounds.xMin, state.zeroKeyConstantValue));
|
||||
var p2 = CurveToCanvas(new Vector3(bounds.xMax, state.zeroKeyConstantValue));
|
||||
Handles.DrawAAPolyLine(state.width, p1, p2);
|
||||
}
|
||||
else if (length == 1)
|
||||
{
|
||||
var p1 = CurveToCanvas(new Vector3(bounds.xMin, keys[0].value));
|
||||
var p2 = CurveToCanvas(new Vector3(bounds.xMax, keys[0].value));
|
||||
Handles.DrawAAPolyLine(state.width, p1, p2);
|
||||
}
|
||||
else
|
||||
{
|
||||
var prevKey = keys[0];
|
||||
for (int k = 1; k < length; k++)
|
||||
{
|
||||
var key = keys[k];
|
||||
var pts = BezierSegment(prevKey, key);
|
||||
|
||||
if (float.IsInfinity(prevKey.outTangent) || float.IsInfinity(key.inTangent))
|
||||
{
|
||||
var s = HardSegment(prevKey, key);
|
||||
Handles.DrawAAPolyLine(state.width, s[0], s[1], s[2]);
|
||||
}
|
||||
else Handles.DrawBezier(pts[0], pts[3], pts[1], pts[2], color, null, state.width);
|
||||
|
||||
prevKey = key;
|
||||
}
|
||||
|
||||
// Curve extents & loops
|
||||
if (keys[0].time > bounds.xMin)
|
||||
{
|
||||
if (state.loopInBounds)
|
||||
{
|
||||
var p1 = keys[length - 1];
|
||||
p1.time -= settings.bounds.width;
|
||||
var p2 = keys[0];
|
||||
var pts = BezierSegment(p1, p2);
|
||||
|
||||
if (float.IsInfinity(p1.outTangent) || float.IsInfinity(p2.inTangent))
|
||||
{
|
||||
var s = HardSegment(p1, p2);
|
||||
Handles.DrawAAPolyLine(state.width, s[0], s[1], s[2]);
|
||||
}
|
||||
else Handles.DrawBezier(pts[0], pts[3], pts[1], pts[2], color, null, state.width);
|
||||
}
|
||||
else
|
||||
{
|
||||
var p1 = CurveToCanvas(new Vector3(bounds.xMin, keys[0].value));
|
||||
var p2 = CurveToCanvas(keys[0]);
|
||||
Handles.DrawAAPolyLine(state.width, p1, p2);
|
||||
}
|
||||
}
|
||||
|
||||
if (keys[length - 1].time < bounds.xMax)
|
||||
{
|
||||
if (state.loopInBounds)
|
||||
{
|
||||
var p1 = keys[length - 1];
|
||||
var p2 = keys[0];
|
||||
p2.time += settings.bounds.width;
|
||||
var pts = BezierSegment(p1, p2);
|
||||
|
||||
if (float.IsInfinity(p1.outTangent) || float.IsInfinity(p2.inTangent))
|
||||
{
|
||||
var s = HardSegment(p1, p2);
|
||||
Handles.DrawAAPolyLine(state.width, s[0], s[1], s[2]);
|
||||
}
|
||||
else Handles.DrawBezier(pts[0], pts[3], pts[1], pts[2], color, null, state.width);
|
||||
}
|
||||
else
|
||||
{
|
||||
var p1 = CurveToCanvas(keys[length - 1]);
|
||||
var p2 = CurveToCanvas(new Vector3(bounds.xMax, keys[length - 1].value));
|
||||
Handles.DrawAAPolyLine(state.width, p1, p2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure selection is correct (undo can break it)
|
||||
bool isCurrentlySelectedCurve = curve == m_SelectedCurve;
|
||||
|
||||
if (isCurrentlySelectedCurve && m_SelectedKeyframeIndex >= length)
|
||||
m_SelectedKeyframeIndex = -1;
|
||||
|
||||
// Handles & keys
|
||||
for (int k = 0; k < length; k++)
|
||||
{
|
||||
bool isCurrentlySelectedKeyframe = k == m_SelectedKeyframeIndex;
|
||||
var e = Event.current;
|
||||
|
||||
var pos = CurveToCanvas(keys[k]);
|
||||
var hitRect = new Rect(pos.x - 8f, pos.y - 8f, 16f, 16f);
|
||||
var offset = isCurrentlySelectedCurve
|
||||
? new RectOffset(5, 5, 5, 5)
|
||||
: new RectOffset(6, 6, 6, 6);
|
||||
|
||||
var outTangent = pos + CurveTangentToCanvas(keys[k].outTangent).normalized * 40f;
|
||||
var inTangent = pos - CurveTangentToCanvas(keys[k].inTangent).normalized * 40f;
|
||||
var inTangentHitRect = new Rect(inTangent.x - 7f, inTangent.y - 7f, 14f, 14f);
|
||||
var outTangentHitrect = new Rect(outTangent.x - 7f, outTangent.y - 7f, 14f, 14f);
|
||||
|
||||
// Draw
|
||||
if (state.showNonEditableHandles)
|
||||
{
|
||||
if (e.type == EventType.Repaint)
|
||||
{
|
||||
var selectedColor = (isCurrentlySelectedCurve && isCurrentlySelectedKeyframe)
|
||||
? settings.selectionColor
|
||||
: state.color;
|
||||
|
||||
// Keyframe
|
||||
EditorGUI.DrawRect(offset.Remove(hitRect), selectedColor);
|
||||
|
||||
// Tangents
|
||||
if (isCurrentlySelectedCurve && (!state.onlyShowHandlesOnSelection || (state.onlyShowHandlesOnSelection && isCurrentlySelectedKeyframe)))
|
||||
{
|
||||
Handles.color = selectedColor;
|
||||
|
||||
if (k > 0 || state.loopInBounds)
|
||||
{
|
||||
Handles.DrawAAPolyLine(state.handleWidth, pos, inTangent);
|
||||
EditorGUI.DrawRect(offset.Remove(inTangentHitRect), selectedColor);
|
||||
}
|
||||
|
||||
if (k < length - 1 || state.loopInBounds)
|
||||
{
|
||||
Handles.DrawAAPolyLine(state.handleWidth, pos, outTangent);
|
||||
EditorGUI.DrawRect(offset.Remove(outTangentHitrect), selectedColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Events
|
||||
if (state.editable)
|
||||
{
|
||||
// Keyframe move
|
||||
if (m_EditMode == EditMode.Moving && e.type == EventType.MouseDrag && isCurrentlySelectedCurve && isCurrentlySelectedKeyframe)
|
||||
{
|
||||
EditMoveKeyframe(animCurve, keys, k);
|
||||
}
|
||||
|
||||
// Tangent editing
|
||||
if (m_EditMode == EditMode.TangentEdit && e.type == EventType.MouseDrag && isCurrentlySelectedCurve && isCurrentlySelectedKeyframe)
|
||||
{
|
||||
bool alreadyBroken = !(Mathf.Approximately(keys[k].inTangent, keys[k].outTangent) || (float.IsInfinity(keys[k].inTangent) && float.IsInfinity(keys[k].outTangent)));
|
||||
EditMoveTangent(animCurve, keys, k, m_TangentEditMode, e.shift || !(alreadyBroken || e.control));
|
||||
}
|
||||
|
||||
// Keyframe selection & context menu
|
||||
if (e.type == EventType.MouseDown && rect.Contains(e.mousePosition))
|
||||
{
|
||||
if (hitRect.Contains(e.mousePosition))
|
||||
{
|
||||
if (e.button == 0)
|
||||
{
|
||||
SelectKeyframe(curve, k);
|
||||
m_EditMode = EditMode.Moving;
|
||||
e.Use();
|
||||
}
|
||||
else if (e.button == 1)
|
||||
{
|
||||
// Keyframe context menu
|
||||
var menu = new GenericMenu();
|
||||
menu.AddItem(new GUIContent("Delete Key"), false, (x) =>
|
||||
{
|
||||
var action = (MenuAction)x;
|
||||
var curveValue = action.curve.animationCurveValue;
|
||||
action.curve.serializedObject.Update();
|
||||
RemoveKeyframe(curveValue, action.index);
|
||||
m_SelectedKeyframeIndex = -1;
|
||||
SaveCurve(action.curve, curveValue);
|
||||
action.curve.serializedObject.ApplyModifiedProperties();
|
||||
}, new MenuAction(curve, k));
|
||||
menu.ShowAsContext();
|
||||
e.Use();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tangent selection & edit mode
|
||||
if (e.type == EventType.MouseDown && rect.Contains(e.mousePosition))
|
||||
{
|
||||
if (inTangentHitRect.Contains(e.mousePosition) && (k > 0 || state.loopInBounds))
|
||||
{
|
||||
SelectKeyframe(curve, k);
|
||||
m_EditMode = EditMode.TangentEdit;
|
||||
m_TangentEditMode = Tangent.In;
|
||||
e.Use();
|
||||
}
|
||||
else if (outTangentHitrect.Contains(e.mousePosition) && (k < length - 1 || state.loopInBounds))
|
||||
{
|
||||
SelectKeyframe(curve, k);
|
||||
m_EditMode = EditMode.TangentEdit;
|
||||
m_TangentEditMode = Tangent.Out;
|
||||
e.Use();
|
||||
}
|
||||
}
|
||||
|
||||
// Mouse up - clean up states
|
||||
if (e.rawType == EventType.MouseUp && m_EditMode != EditMode.None)
|
||||
{
|
||||
m_EditMode = EditMode.None;
|
||||
}
|
||||
|
||||
// Set cursors
|
||||
{
|
||||
EditorGUIUtility.AddCursorRect(hitRect, MouseCursor.MoveArrow);
|
||||
|
||||
if (k > 0 || state.loopInBounds)
|
||||
EditorGUIUtility.AddCursorRect(inTangentHitRect, MouseCursor.RotateArrow);
|
||||
|
||||
if (k < length - 1 || state.loopInBounds)
|
||||
EditorGUIUtility.AddCursorRect(outTangentHitrect, MouseCursor.RotateArrow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Handles.color = Color.white;
|
||||
SaveCurve(curve, animCurve);
|
||||
}
|
||||
|
||||
void OnGeneralUI(Rect rect)
|
||||
{
|
||||
var e = Event.current;
|
||||
|
||||
// Selection
|
||||
if (e.type == EventType.MouseDown)
|
||||
{
|
||||
GUI.FocusControl(null);
|
||||
m_SelectedCurve = null;
|
||||
m_SelectedKeyframeIndex = -1;
|
||||
bool used = false;
|
||||
|
||||
var hit = CanvasToCurve(e.mousePosition);
|
||||
float curvePickValue = CurveToCanvas(hit).y;
|
||||
|
||||
// Try and select a curve
|
||||
foreach (var curve in m_Curves)
|
||||
{
|
||||
if (!curve.Value.editable || !curve.Value.visible)
|
||||
continue;
|
||||
|
||||
var prop = curve.Key;
|
||||
var state = curve.Value;
|
||||
var animCurve = prop.animationCurveValue;
|
||||
float hitY = animCurve.length == 0
|
||||
? state.zeroKeyConstantValue
|
||||
: animCurve.Evaluate(hit.x);
|
||||
|
||||
var curvePos = CurveToCanvas(new Vector3(hit.x, hitY));
|
||||
|
||||
if (Mathf.Abs(curvePos.y - curvePickValue) < settings.curvePickingDistance)
|
||||
{
|
||||
m_SelectedCurve = prop;
|
||||
|
||||
if (e.clickCount == 2 && e.button == 0)
|
||||
{
|
||||
// Create a keyframe on double-click on this curve
|
||||
EditCreateKeyframe(animCurve, hit, true, state.zeroKeyConstantValue);
|
||||
SaveCurve(prop, animCurve);
|
||||
}
|
||||
else if (e.button == 1)
|
||||
{
|
||||
// Curve context menu
|
||||
var menu = new GenericMenu();
|
||||
menu.AddItem(new GUIContent("Add Key"), false, (x) =>
|
||||
{
|
||||
var action = (MenuAction)x;
|
||||
var curveValue = action.curve.animationCurveValue;
|
||||
action.curve.serializedObject.Update();
|
||||
EditCreateKeyframe(curveValue, hit, true, 0f);
|
||||
SaveCurve(action.curve, curveValue);
|
||||
action.curve.serializedObject.ApplyModifiedProperties();
|
||||
}, new MenuAction(prop, hit));
|
||||
menu.ShowAsContext();
|
||||
e.Use();
|
||||
used = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (e.clickCount == 2 && e.button == 0 && m_SelectedCurve == null)
|
||||
{
|
||||
// Create a keyframe on every curve on double-click
|
||||
foreach (var curve in m_Curves)
|
||||
{
|
||||
if (!curve.Value.editable || !curve.Value.visible)
|
||||
continue;
|
||||
|
||||
var prop = curve.Key;
|
||||
var state = curve.Value;
|
||||
var animCurve = prop.animationCurveValue;
|
||||
EditCreateKeyframe(animCurve, hit, e.alt, state.zeroKeyConstantValue);
|
||||
SaveCurve(prop, animCurve);
|
||||
}
|
||||
}
|
||||
else if (!used && e.button == 1)
|
||||
{
|
||||
// Global context menu
|
||||
var menu = new GenericMenu();
|
||||
menu.AddItem(new GUIContent("Add Key At Position"), false, () => ContextMenuAddKey(hit, false));
|
||||
menu.AddItem(new GUIContent("Add Key On Curves"), false, () => ContextMenuAddKey(hit, true));
|
||||
menu.ShowAsContext();
|
||||
}
|
||||
|
||||
e.Use();
|
||||
}
|
||||
|
||||
// Delete selected key(s)
|
||||
if (e.type == EventType.KeyDown && (e.keyCode == KeyCode.Delete || e.keyCode == KeyCode.Backspace))
|
||||
{
|
||||
if (m_SelectedKeyframeIndex != -1 && m_SelectedCurve != null)
|
||||
{
|
||||
var animCurve = m_SelectedCurve.animationCurveValue;
|
||||
var length = animCurve.length;
|
||||
|
||||
if (m_Curves[m_SelectedCurve].minPointCount < length && length >= 0)
|
||||
{
|
||||
EditDeleteKeyframe(animCurve, m_SelectedKeyframeIndex);
|
||||
m_SelectedKeyframeIndex = -1;
|
||||
SaveCurve(m_SelectedCurve, animCurve);
|
||||
}
|
||||
|
||||
e.Use();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SaveCurve(SerializedProperty prop, AnimationCurve curve)
|
||||
{
|
||||
prop.animationCurveValue = curve;
|
||||
}
|
||||
|
||||
void Invalidate()
|
||||
{
|
||||
m_Dirty = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Keyframe manipulations
|
||||
|
||||
void SelectKeyframe(SerializedProperty curve, int keyframeIndex)
|
||||
{
|
||||
m_SelectedKeyframeIndex = keyframeIndex;
|
||||
m_SelectedCurve = curve;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void ContextMenuAddKey(Vector3 hit, bool createOnCurve)
|
||||
{
|
||||
SerializedObject serializedObject = null;
|
||||
|
||||
foreach (var curve in m_Curves)
|
||||
{
|
||||
if (!curve.Value.editable || !curve.Value.visible)
|
||||
continue;
|
||||
|
||||
var prop = curve.Key;
|
||||
var state = curve.Value;
|
||||
|
||||
if (serializedObject == null)
|
||||
{
|
||||
serializedObject = prop.serializedObject;
|
||||
serializedObject.Update();
|
||||
}
|
||||
|
||||
var animCurve = prop.animationCurveValue;
|
||||
EditCreateKeyframe(animCurve, hit, createOnCurve, state.zeroKeyConstantValue);
|
||||
SaveCurve(prop, animCurve);
|
||||
}
|
||||
|
||||
if (serializedObject != null)
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void EditCreateKeyframe(AnimationCurve curve, Vector3 position, bool createOnCurve, float zeroKeyConstantValue)
|
||||
{
|
||||
float tangent = EvaluateTangent(curve, position.x);
|
||||
|
||||
if (createOnCurve)
|
||||
{
|
||||
position.y = curve.length == 0
|
||||
? zeroKeyConstantValue
|
||||
: curve.Evaluate(position.x);
|
||||
}
|
||||
|
||||
AddKeyframe(curve, new Keyframe(position.x, position.y, tangent, tangent));
|
||||
}
|
||||
|
||||
void EditDeleteKeyframe(AnimationCurve curve, int keyframeIndex)
|
||||
{
|
||||
RemoveKeyframe(curve, keyframeIndex);
|
||||
}
|
||||
|
||||
void AddKeyframe(AnimationCurve curve, Keyframe newValue)
|
||||
{
|
||||
curve.AddKey(newValue);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void RemoveKeyframe(AnimationCurve curve, int keyframeIndex)
|
||||
{
|
||||
curve.RemoveKey(keyframeIndex);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void SetKeyframe(AnimationCurve curve, int keyframeIndex, Keyframe newValue)
|
||||
{
|
||||
var keys = curve.keys;
|
||||
|
||||
if (keyframeIndex > 0)
|
||||
newValue.time = Mathf.Max(keys[keyframeIndex - 1].time + settings.keyTimeClampingDistance, newValue.time);
|
||||
|
||||
if (keyframeIndex < keys.Length - 1)
|
||||
newValue.time = Mathf.Min(keys[keyframeIndex + 1].time - settings.keyTimeClampingDistance, newValue.time);
|
||||
|
||||
curve.MoveKey(keyframeIndex, newValue);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void EditMoveKeyframe(AnimationCurve curve, Keyframe[] keys, int keyframeIndex)
|
||||
{
|
||||
var key = CanvasToCurve(Event.current.mousePosition);
|
||||
float inTgt = keys[keyframeIndex].inTangent;
|
||||
float outTgt = keys[keyframeIndex].outTangent;
|
||||
SetKeyframe(curve, keyframeIndex, new Keyframe(key.x, key.y, inTgt, outTgt));
|
||||
}
|
||||
|
||||
void EditMoveTangent(AnimationCurve curve, Keyframe[] keys, int keyframeIndex, Tangent targetTangent, bool linkTangents)
|
||||
{
|
||||
var pos = CanvasToCurve(Event.current.mousePosition);
|
||||
|
||||
float time = keys[keyframeIndex].time;
|
||||
float value = keys[keyframeIndex].value;
|
||||
|
||||
pos -= new Vector3(time, value);
|
||||
|
||||
if (targetTangent == Tangent.In && pos.x > 0f)
|
||||
pos.x = 0f;
|
||||
|
||||
if (targetTangent == Tangent.Out && pos.x < 0f)
|
||||
pos.x = 0f;
|
||||
|
||||
float tangent;
|
||||
|
||||
if (Mathf.Approximately(pos.x, 0f))
|
||||
tangent = pos.y < 0f ? float.PositiveInfinity : float.NegativeInfinity;
|
||||
else
|
||||
tangent = pos.y / pos.x;
|
||||
|
||||
float inTangent = keys[keyframeIndex].inTangent;
|
||||
float outTangent = keys[keyframeIndex].outTangent;
|
||||
|
||||
if (targetTangent == Tangent.In || linkTangents)
|
||||
inTangent = tangent;
|
||||
if (targetTangent == Tangent.Out || linkTangents)
|
||||
outTangent = tangent;
|
||||
|
||||
SetKeyframe(curve, keyframeIndex, new Keyframe(time, value, inTangent, outTangent));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Maths utilities
|
||||
|
||||
Vector3 CurveToCanvas(Keyframe keyframe)
|
||||
{
|
||||
return CurveToCanvas(new Vector3(keyframe.time, keyframe.value));
|
||||
}
|
||||
|
||||
Vector3 CurveToCanvas(Vector3 position)
|
||||
{
|
||||
var bounds = settings.bounds;
|
||||
var output = new Vector3((position.x - bounds.x) / (bounds.xMax - bounds.x), (position.y - bounds.y) / (bounds.yMax - bounds.y));
|
||||
output.x = output.x * (m_CurveArea.xMax - m_CurveArea.xMin) + m_CurveArea.xMin;
|
||||
output.y = (1f - output.y) * (m_CurveArea.yMax - m_CurveArea.yMin) + m_CurveArea.yMin;
|
||||
return output;
|
||||
}
|
||||
|
||||
Vector3 CanvasToCurve(Vector3 position)
|
||||
{
|
||||
var bounds = settings.bounds;
|
||||
var output = position;
|
||||
output.x = (output.x - m_CurveArea.xMin) / (m_CurveArea.xMax - m_CurveArea.xMin);
|
||||
output.y = (output.y - m_CurveArea.yMin) / (m_CurveArea.yMax - m_CurveArea.yMin);
|
||||
output.x = Mathf.Lerp(bounds.x, bounds.xMax, output.x);
|
||||
output.y = Mathf.Lerp(bounds.yMax, bounds.y, output.y);
|
||||
return output;
|
||||
}
|
||||
|
||||
Vector3 CurveTangentToCanvas(float tangent)
|
||||
{
|
||||
if (!float.IsInfinity(tangent))
|
||||
{
|
||||
var bounds = settings.bounds;
|
||||
float ratio = (m_CurveArea.width / m_CurveArea.height) / ((bounds.xMax - bounds.x) / (bounds.yMax - bounds.y));
|
||||
return new Vector3(1f, -tangent / ratio).normalized;
|
||||
}
|
||||
|
||||
return float.IsPositiveInfinity(tangent) ? Vector3.up : Vector3.down;
|
||||
}
|
||||
|
||||
Vector3[] BezierSegment(Keyframe start, Keyframe end)
|
||||
{
|
||||
var segment = new Vector3[4];
|
||||
|
||||
segment[0] = CurveToCanvas(new Vector3(start.time, start.value));
|
||||
segment[3] = CurveToCanvas(new Vector3(end.time, end.value));
|
||||
|
||||
float middle = start.time + ((end.time - start.time) * 0.333333f);
|
||||
float middle2 = start.time + ((end.time - start.time) * 0.666666f);
|
||||
|
||||
segment[1] = CurveToCanvas(new Vector3(middle, ProjectTangent(start.time, start.value, start.outTangent, middle)));
|
||||
segment[2] = CurveToCanvas(new Vector3(middle2, ProjectTangent(end.time, end.value, end.inTangent, middle2)));
|
||||
|
||||
return segment;
|
||||
}
|
||||
|
||||
Vector3[] HardSegment(Keyframe start, Keyframe end)
|
||||
{
|
||||
var segment = new Vector3[3];
|
||||
|
||||
segment[0] = CurveToCanvas(start);
|
||||
segment[1] = CurveToCanvas(new Vector3(end.time, start.value));
|
||||
segment[2] = CurveToCanvas(end);
|
||||
|
||||
return segment;
|
||||
}
|
||||
|
||||
float ProjectTangent(float inPosition, float inValue, float inTangent, float projPosition)
|
||||
{
|
||||
return inValue + ((projPosition - inPosition) * inTangent);
|
||||
}
|
||||
|
||||
float EvaluateTangent(AnimationCurve curve, float time)
|
||||
{
|
||||
int prev = -1, next = 0;
|
||||
for (int i = 0; i < curve.keys.Length; i++)
|
||||
{
|
||||
if (time > curve.keys[i].time)
|
||||
{
|
||||
prev = i;
|
||||
next = i + 1;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
if (next == 0)
|
||||
return 0f;
|
||||
|
||||
if (prev == curve.keys.Length - 1)
|
||||
return 0f;
|
||||
|
||||
const float kD = 1e-3f;
|
||||
float tp = Mathf.Max(time - kD, curve.keys[prev].time);
|
||||
float tn = Mathf.Min(time + kD, curve.keys[next].time);
|
||||
|
||||
float vp = curve.Evaluate(tp);
|
||||
float vn = curve.Evaluate(tn);
|
||||
|
||||
if (Mathf.Approximately(tn, tp))
|
||||
return (vn - vp > 0f) ? float.PositiveInfinity : float.NegativeInfinity;
|
||||
|
||||
return (vn - vp) / (tn - tp);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
12
Assets/ThirdParty/PostProcessing/Editor/Utils/CurveEditor.cs.meta
vendored
Normal file
12
Assets/ThirdParty/PostProcessing/Editor/Utils/CurveEditor.cs.meta
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afb349ef0bffd144db2bdd25630f648e
|
||||
timeCreated: 1472650750
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
194
Assets/ThirdParty/PostProcessing/Editor/Utils/EditorGUIHelper.cs
vendored
Normal file
194
Assets/ThirdParty/PostProcessing/Editor/Utils/EditorGUIHelper.cs
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using UnityEngine.PostProcessing;
|
||||
|
||||
namespace UnityEditor.PostProcessing
|
||||
{
|
||||
public static class EditorGUIHelper
|
||||
{
|
||||
static EditorGUIHelper()
|
||||
{
|
||||
s_GUIContentCache = new Dictionary<string, GUIContent>();
|
||||
}
|
||||
|
||||
#region GUIContent caching
|
||||
|
||||
static Dictionary<string, GUIContent> s_GUIContentCache;
|
||||
|
||||
public static GUIContent GetContent(string textAndTooltip)
|
||||
{
|
||||
if (string.IsNullOrEmpty(textAndTooltip))
|
||||
return GUIContent.none;
|
||||
|
||||
GUIContent content;
|
||||
|
||||
if (!s_GUIContentCache.TryGetValue(textAndTooltip, out content))
|
||||
{
|
||||
var s = textAndTooltip.Split('|');
|
||||
content = new GUIContent(s[0]);
|
||||
|
||||
if (s.Length > 1 && !string.IsNullOrEmpty(s[1]))
|
||||
content.tooltip = s[1];
|
||||
|
||||
s_GUIContentCache.Add(textAndTooltip, content);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static bool Header(string title, SerializedProperty group, Action resetAction)
|
||||
{
|
||||
var rect = GUILayoutUtility.GetRect(16f, 22f, FxStyles.header);
|
||||
GUI.Box(rect, title, FxStyles.header);
|
||||
|
||||
var display = group == null || group.isExpanded;
|
||||
|
||||
var foldoutRect = new Rect(rect.x + 4f, rect.y + 2f, 13f, 13f);
|
||||
var e = Event.current;
|
||||
|
||||
var popupRect = new Rect(rect.x + rect.width - FxStyles.paneOptionsIcon.width - 5f, rect.y + FxStyles.paneOptionsIcon.height / 2f + 1f, FxStyles.paneOptionsIcon.width, FxStyles.paneOptionsIcon.height);
|
||||
GUI.DrawTexture(popupRect, FxStyles.paneOptionsIcon);
|
||||
|
||||
if (e.type == EventType.Repaint)
|
||||
FxStyles.headerFoldout.Draw(foldoutRect, false, false, display, false);
|
||||
|
||||
if (e.type == EventType.MouseDown)
|
||||
{
|
||||
if (popupRect.Contains(e.mousePosition))
|
||||
{
|
||||
var popup = new GenericMenu();
|
||||
popup.AddItem(GetContent("Reset"), false, () => resetAction());
|
||||
popup.AddSeparator(string.Empty);
|
||||
popup.AddItem(GetContent("Copy Settings"), false, () => CopySettings(group));
|
||||
|
||||
if (CanPaste(group))
|
||||
popup.AddItem(GetContent("Paste Settings"), false, () => PasteSettings(group));
|
||||
else
|
||||
popup.AddDisabledItem(GetContent("Paste Settings"));
|
||||
|
||||
popup.ShowAsContext();
|
||||
}
|
||||
else if (rect.Contains(e.mousePosition) && group != null)
|
||||
{
|
||||
display = !display;
|
||||
|
||||
if (group != null)
|
||||
group.isExpanded = !group.isExpanded;
|
||||
|
||||
e.Use();
|
||||
}
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
public static bool Header(string title, SerializedProperty group, SerializedProperty enabledField, Action resetAction)
|
||||
{
|
||||
var field = ReflectionUtils.GetFieldInfoFromPath(enabledField.serializedObject.targetObject, enabledField.propertyPath);
|
||||
object parent = null;
|
||||
PropertyInfo prop = null;
|
||||
|
||||
if (field != null && field.IsDefined(typeof(GetSetAttribute), false))
|
||||
{
|
||||
var attr = (GetSetAttribute)field.GetCustomAttributes(typeof(GetSetAttribute), false)[0];
|
||||
parent = ReflectionUtils.GetParentObject(enabledField.propertyPath, enabledField.serializedObject.targetObject);
|
||||
prop = parent.GetType().GetProperty(attr.name);
|
||||
}
|
||||
|
||||
var display = group == null || group.isExpanded;
|
||||
var enabled = enabledField.boolValue;
|
||||
|
||||
var rect = GUILayoutUtility.GetRect(16f, 22f, FxStyles.header);
|
||||
GUI.Box(rect, title, FxStyles.header);
|
||||
|
||||
var toggleRect = new Rect(rect.x + 4f, rect.y + 4f, 13f, 13f);
|
||||
var e = Event.current;
|
||||
|
||||
var popupRect = new Rect(rect.x + rect.width - FxStyles.paneOptionsIcon.width - 5f, rect.y + FxStyles.paneOptionsIcon.height / 2f + 1f, FxStyles.paneOptionsIcon.width, FxStyles.paneOptionsIcon.height);
|
||||
GUI.DrawTexture(popupRect, FxStyles.paneOptionsIcon);
|
||||
|
||||
if (e.type == EventType.Repaint)
|
||||
FxStyles.headerCheckbox.Draw(toggleRect, false, false, enabled, false);
|
||||
|
||||
if (e.type == EventType.MouseDown)
|
||||
{
|
||||
const float kOffset = 2f;
|
||||
toggleRect.x -= kOffset;
|
||||
toggleRect.y -= kOffset;
|
||||
toggleRect.width += kOffset * 2f;
|
||||
toggleRect.height += kOffset * 2f;
|
||||
|
||||
if (toggleRect.Contains(e.mousePosition))
|
||||
{
|
||||
enabledField.boolValue = !enabledField.boolValue;
|
||||
|
||||
if (prop != null)
|
||||
prop.SetValue(parent, enabledField.boolValue, null);
|
||||
|
||||
e.Use();
|
||||
}
|
||||
else if (popupRect.Contains(e.mousePosition))
|
||||
{
|
||||
var popup = new GenericMenu();
|
||||
popup.AddItem(GetContent("Reset"), false, () => resetAction());
|
||||
popup.AddSeparator(string.Empty);
|
||||
popup.AddItem(GetContent("Copy Settings"), false, () => CopySettings(group));
|
||||
|
||||
if (CanPaste(group))
|
||||
popup.AddItem(GetContent("Paste Settings"), false, () => PasteSettings(group));
|
||||
else
|
||||
popup.AddDisabledItem(GetContent("Paste Settings"));
|
||||
|
||||
popup.ShowAsContext();
|
||||
}
|
||||
else if (rect.Contains(e.mousePosition) && group != null)
|
||||
{
|
||||
display = !display;
|
||||
group.isExpanded = !group.isExpanded;
|
||||
e.Use();
|
||||
}
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
static void CopySettings(SerializedProperty settings)
|
||||
{
|
||||
var t = typeof(PostProcessingProfile);
|
||||
var settingsStruct = ReflectionUtils.GetFieldValueFromPath(settings.serializedObject.targetObject, ref t, settings.propertyPath);
|
||||
var serializedString = t.ToString() + '|' + JsonUtility.ToJson(settingsStruct);
|
||||
EditorGUIUtility.systemCopyBuffer = serializedString;
|
||||
}
|
||||
|
||||
static bool CanPaste(SerializedProperty settings)
|
||||
{
|
||||
var data = EditorGUIUtility.systemCopyBuffer;
|
||||
|
||||
if (string.IsNullOrEmpty(data))
|
||||
return false;
|
||||
|
||||
var parts = data.Split('|');
|
||||
|
||||
if (string.IsNullOrEmpty(parts[0]))
|
||||
return false;
|
||||
|
||||
var field = ReflectionUtils.GetFieldInfoFromPath(settings.serializedObject.targetObject, settings.propertyPath);
|
||||
return parts[0] == field.FieldType.ToString();
|
||||
}
|
||||
|
||||
static void PasteSettings(SerializedProperty settings)
|
||||
{
|
||||
Undo.RecordObject(settings.serializedObject.targetObject, "Paste effect settings");
|
||||
var field = ReflectionUtils.GetFieldInfoFromPath(settings.serializedObject.targetObject, settings.propertyPath);
|
||||
var json = EditorGUIUtility.systemCopyBuffer.Substring(field.FieldType.ToString().Length + 1);
|
||||
var obj = JsonUtility.FromJson(json, field.FieldType);
|
||||
var parent = ReflectionUtils.GetParentObject(settings.propertyPath, settings.serializedObject.targetObject);
|
||||
field.SetValue(parent, obj, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CultureInfo.CurrentCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/ThirdParty/PostProcessing/Editor/Utils/EditorGUIHelper.cs.meta
vendored
Normal file
12
Assets/ThirdParty/PostProcessing/Editor/Utils/EditorGUIHelper.cs.meta
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7226e17fa48c86148a3d15584e21b4cb
|
||||
timeCreated: 1460477750
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
58
Assets/ThirdParty/PostProcessing/Editor/Utils/EditorResources.cs
vendored
Normal file
58
Assets/ThirdParty/PostProcessing/Editor/Utils/EditorResources.cs
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.PostProcessing
|
||||
{
|
||||
using UnityObject = Object;
|
||||
|
||||
static class EditorResources
|
||||
{
|
||||
static string m_EditorResourcesPath = string.Empty;
|
||||
|
||||
internal static string editorResourcesPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(m_EditorResourcesPath))
|
||||
{
|
||||
string path;
|
||||
|
||||
if (SearchForEditorResourcesPath(out path))
|
||||
m_EditorResourcesPath = path;
|
||||
else
|
||||
Debug.LogError("Unable to locate editor resources. Make sure the PostProcessing package has been installed correctly.");
|
||||
}
|
||||
|
||||
return m_EditorResourcesPath;
|
||||
}
|
||||
}
|
||||
|
||||
internal static T Load<T>(string name)
|
||||
where T : UnityObject
|
||||
{
|
||||
return AssetDatabase.LoadAssetAtPath<T>(editorResourcesPath + name);
|
||||
}
|
||||
|
||||
static bool SearchForEditorResourcesPath(out string path)
|
||||
{
|
||||
path = string.Empty;
|
||||
|
||||
string searchStr = "/PostProcessing/Editor Resources/";
|
||||
string str = null;
|
||||
|
||||
foreach (var assetPath in AssetDatabase.GetAllAssetPaths())
|
||||
{
|
||||
if (assetPath.Contains(searchStr))
|
||||
{
|
||||
str = assetPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (str == null)
|
||||
return false;
|
||||
|
||||
path = str.Substring(0, str.LastIndexOf(searchStr) + searchStr.Length);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/ThirdParty/PostProcessing/Editor/Utils/EditorResources.cs.meta
vendored
Normal file
12
Assets/ThirdParty/PostProcessing/Editor/Utils/EditorResources.cs.meta
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a66d7b0165140a1439be89b5afc000fb
|
||||
timeCreated: 1476177015
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
111
Assets/ThirdParty/PostProcessing/Editor/Utils/FxStyles.cs
vendored
Normal file
111
Assets/ThirdParty/PostProcessing/Editor/Utils/FxStyles.cs
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.PostProcessing
|
||||
{
|
||||
public static class FxStyles
|
||||
{
|
||||
public static GUIStyle tickStyleRight;
|
||||
public static GUIStyle tickStyleLeft;
|
||||
public static GUIStyle tickStyleCenter;
|
||||
|
||||
public static GUIStyle preSlider;
|
||||
public static GUIStyle preSliderThumb;
|
||||
public static GUIStyle preButton;
|
||||
public static GUIStyle preDropdown;
|
||||
|
||||
public static GUIStyle preLabel;
|
||||
public static GUIStyle hueCenterCursor;
|
||||
public static GUIStyle hueRangeCursor;
|
||||
|
||||
public static GUIStyle centeredBoldLabel;
|
||||
public static GUIStyle wheelThumb;
|
||||
public static Vector2 wheelThumbSize;
|
||||
|
||||
public static GUIStyle header;
|
||||
public static GUIStyle headerCheckbox;
|
||||
public static GUIStyle headerFoldout;
|
||||
|
||||
public static Texture2D playIcon;
|
||||
public static Texture2D checkerIcon;
|
||||
public static Texture2D paneOptionsIcon;
|
||||
|
||||
public static GUIStyle centeredMiniLabel;
|
||||
|
||||
static FxStyles()
|
||||
{
|
||||
tickStyleRight = new GUIStyle("Label")
|
||||
{
|
||||
alignment = TextAnchor.MiddleRight,
|
||||
fontSize = 9
|
||||
};
|
||||
|
||||
tickStyleLeft = new GUIStyle("Label")
|
||||
{
|
||||
alignment = TextAnchor.MiddleLeft,
|
||||
fontSize = 9
|
||||
};
|
||||
|
||||
tickStyleCenter = new GUIStyle("Label")
|
||||
{
|
||||
alignment = TextAnchor.MiddleCenter,
|
||||
fontSize = 9
|
||||
};
|
||||
|
||||
preSlider = new GUIStyle("PreSlider");
|
||||
preSliderThumb = new GUIStyle("PreSliderThumb");
|
||||
preButton = new GUIStyle("PreButton");
|
||||
preDropdown = new GUIStyle("preDropdown");
|
||||
|
||||
preLabel = new GUIStyle("ShurikenLabel");
|
||||
|
||||
hueCenterCursor = new GUIStyle("ColorPicker2DThumb")
|
||||
{
|
||||
normal = { background = (Texture2D)EditorGUIUtility.LoadRequired("Builtin Skins/DarkSkin/Images/ShurikenPlus.png") },
|
||||
fixedWidth = 6,
|
||||
fixedHeight = 6
|
||||
};
|
||||
|
||||
hueRangeCursor = new GUIStyle(hueCenterCursor)
|
||||
{
|
||||
normal = { background = (Texture2D)EditorGUIUtility.LoadRequired("Builtin Skins/DarkSkin/Images/CircularToggle_ON.png") }
|
||||
};
|
||||
|
||||
wheelThumb = new GUIStyle("ColorPicker2DThumb");
|
||||
|
||||
centeredBoldLabel = new GUIStyle(GUI.skin.GetStyle("Label"))
|
||||
{
|
||||
alignment = TextAnchor.UpperCenter,
|
||||
fontStyle = FontStyle.Bold
|
||||
};
|
||||
|
||||
centeredMiniLabel = new GUIStyle(EditorStyles.centeredGreyMiniLabel)
|
||||
{
|
||||
alignment = TextAnchor.UpperCenter
|
||||
};
|
||||
|
||||
wheelThumbSize = new Vector2(
|
||||
!Mathf.Approximately(wheelThumb.fixedWidth, 0f) ? wheelThumb.fixedWidth : wheelThumb.padding.horizontal,
|
||||
!Mathf.Approximately(wheelThumb.fixedHeight, 0f) ? wheelThumb.fixedHeight : wheelThumb.padding.vertical
|
||||
);
|
||||
|
||||
header = new GUIStyle("ShurikenModuleTitle")
|
||||
{
|
||||
font = (new GUIStyle("Label")).font,
|
||||
border = new RectOffset(15, 7, 4, 4),
|
||||
fixedHeight = 22,
|
||||
contentOffset = new Vector2(20f, -2f)
|
||||
};
|
||||
|
||||
headerCheckbox = new GUIStyle("ShurikenCheckMark");
|
||||
headerFoldout = new GUIStyle("Foldout");
|
||||
|
||||
playIcon = (Texture2D)EditorGUIUtility.LoadRequired("Builtin Skins/DarkSkin/Images/IN foldout act.png");
|
||||
checkerIcon = (Texture2D)EditorGUIUtility.LoadRequired("Icons/CheckerFloor.png");
|
||||
|
||||
if (EditorGUIUtility.isProSkin)
|
||||
paneOptionsIcon = (Texture2D)EditorGUIUtility.LoadRequired("Builtin Skins/DarkSkin/Images/pane options.png");
|
||||
else
|
||||
paneOptionsIcon = (Texture2D)EditorGUIUtility.LoadRequired("Builtin Skins/LightSkin/Images/pane options.png");
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/ThirdParty/PostProcessing/Editor/Utils/FxStyles.cs.meta
vendored
Normal file
12
Assets/ThirdParty/PostProcessing/Editor/Utils/FxStyles.cs.meta
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f31cf52f05e80c4ea48570d0c3c8f59
|
||||
timeCreated: 1461744717
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
124
Assets/ThirdParty/PostProcessing/Editor/Utils/ReflectionUtils.cs
vendored
Normal file
124
Assets/ThirdParty/PostProcessing/Editor/Utils/ReflectionUtils.cs
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace UnityEditor.PostProcessing
|
||||
{
|
||||
public static class ReflectionUtils
|
||||
{
|
||||
static Dictionary<KeyValuePair<object, string>, FieldInfo> s_FieldInfoFromPaths = new Dictionary<KeyValuePair<object, string>, FieldInfo>();
|
||||
|
||||
public static FieldInfo GetFieldInfoFromPath(object source, string path)
|
||||
{
|
||||
FieldInfo field = null;
|
||||
var kvp = new KeyValuePair<object, string>(source, path);
|
||||
|
||||
if (!s_FieldInfoFromPaths.TryGetValue(kvp, out field))
|
||||
{
|
||||
var splittedPath = path.Split('.');
|
||||
var type = source.GetType();
|
||||
|
||||
foreach (var t in splittedPath)
|
||||
{
|
||||
field = type.GetField(t, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
|
||||
if (field == null)
|
||||
break;
|
||||
|
||||
type = field.FieldType;
|
||||
}
|
||||
|
||||
s_FieldInfoFromPaths.Add(kvp, field);
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
public static string GetFieldPath<T, TValue>(Expression<Func<T, TValue>> expr)
|
||||
{
|
||||
MemberExpression me;
|
||||
switch (expr.Body.NodeType)
|
||||
{
|
||||
case ExpressionType.Convert:
|
||||
case ExpressionType.ConvertChecked:
|
||||
var ue = expr.Body as UnaryExpression;
|
||||
me = (ue != null ? ue.Operand : null) as MemberExpression;
|
||||
break;
|
||||
default:
|
||||
me = expr.Body as MemberExpression;
|
||||
break;
|
||||
}
|
||||
|
||||
var members = new List<string>();
|
||||
while (me != null)
|
||||
{
|
||||
members.Add(me.Member.Name);
|
||||
me = me.Expression as MemberExpression;
|
||||
}
|
||||
|
||||
var sb = new StringBuilder();
|
||||
for (int i = members.Count - 1; i >= 0; i--)
|
||||
{
|
||||
sb.Append(members[i]);
|
||||
if (i > 0) sb.Append('.');
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static object GetFieldValue(object source, string name)
|
||||
{
|
||||
var type = source.GetType();
|
||||
|
||||
while (type != null)
|
||||
{
|
||||
var f = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
if (f != null)
|
||||
return f.GetValue(source);
|
||||
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static object GetFieldValueFromPath(object source, ref Type baseType, string path)
|
||||
{
|
||||
var splittedPath = path.Split('.');
|
||||
object srcObject = source;
|
||||
|
||||
foreach (var t in splittedPath)
|
||||
{
|
||||
var fieldInfo = baseType.GetField(t, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
|
||||
if (fieldInfo == null)
|
||||
{
|
||||
baseType = null;
|
||||
break;
|
||||
}
|
||||
|
||||
baseType = fieldInfo.FieldType;
|
||||
srcObject = GetFieldValue(srcObject, t);
|
||||
}
|
||||
|
||||
return baseType == null
|
||||
? null
|
||||
: srcObject;
|
||||
}
|
||||
|
||||
public static object GetParentObject(string path, object obj)
|
||||
{
|
||||
var fields = path.Split('.');
|
||||
|
||||
if (fields.Length == 1)
|
||||
return obj;
|
||||
|
||||
var info = obj.GetType().GetField(fields[0], BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
obj = info.GetValue(obj);
|
||||
|
||||
return GetParentObject(string.Join(".", fields, 1, fields.Length - 1), obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/ThirdParty/PostProcessing/Editor/Utils/ReflectionUtils.cs.meta
vendored
Normal file
12
Assets/ThirdParty/PostProcessing/Editor/Utils/ReflectionUtils.cs.meta
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71f7e805a7fc35046afbcf5c2639d116
|
||||
timeCreated: 1466604313
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user