340 lines
14 KiB
C#
340 lines
14 KiB
C#
namespace Dreamteck.Splines.Editor
|
|
{
|
|
using UnityEngine;
|
|
using UnityEditor;
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
|
public static class SplineEditorGUI
|
|
{
|
|
public static readonly GUIStyle leftButtonStyle, midButtonStyle, rightButtonStyle, boxStyle;
|
|
|
|
private static Color previousContentColor, previousBackgroundColor, highLightBGColor, highlightContentColor;
|
|
|
|
|
|
public static readonly GUIStyle defaultButton = null;
|
|
public static readonly GUIStyle defaultEditorButton = null;
|
|
public static readonly GUIStyle defaultEditorButtonSelected = null;
|
|
public static readonly GUIStyle dropdownItem = null;
|
|
public static readonly GUIStyle bigButton = null;
|
|
public static readonly GUIStyle bigButtonSelected = null;
|
|
public static readonly GUIStyle labelText = null;
|
|
public static GUIStyle whiteBox
|
|
{
|
|
get
|
|
{
|
|
if (_whiteBox.normal.background == null) _whiteBox.normal.background = white;
|
|
return _whiteBox;
|
|
}
|
|
}
|
|
private static readonly GUIStyle _whiteBox = null;
|
|
public static GUIStyle defaultField
|
|
{
|
|
get
|
|
{
|
|
if (_defaultField.normal.background == null) _defaultField.normal.background = white;
|
|
return _defaultField;
|
|
}
|
|
}
|
|
private static GUIStyle _defaultField = null;
|
|
public static GUIStyle smallField
|
|
{
|
|
get
|
|
{
|
|
if (_smallField.normal.background == null) _smallField.normal.background = white;
|
|
return _smallField;
|
|
}
|
|
}
|
|
private static GUIStyle _smallField = null;
|
|
public static readonly Color inactiveColor = new Color(0.7f, 0.7f, 0.7f, 0.3f);
|
|
public static readonly Color textColor = new Color(0.2f, 0.2f, 0.2f, 1f);
|
|
public static readonly Color activeColor = new Color(1f, 1f, 1f, 1f);
|
|
public static readonly Color blackColor = new Color(0, 0, 0, 0.7f);
|
|
public static readonly Color buttonContentColor = Color.black;
|
|
private static bool[] controlStates = new bool[0];
|
|
private static string[] floatFieldContents = new string[0];
|
|
private static int controlIndex = 0;
|
|
|
|
public static float scale = 1f;
|
|
public static Texture2D white
|
|
{
|
|
get
|
|
{
|
|
if (_white == null)
|
|
{
|
|
_white = new Texture2D(1, 1);
|
|
_white.SetPixel(0, 0, Color.white);
|
|
_white.Apply();
|
|
}
|
|
return _white;
|
|
}
|
|
}
|
|
private static Texture2D _white = null;
|
|
|
|
public static void Update()
|
|
{
|
|
controlStates = new bool[0];
|
|
floatFieldContents = new string[0];
|
|
}
|
|
|
|
public static void Reset()
|
|
{
|
|
controlIndex = 0;
|
|
}
|
|
|
|
static SplineEditorGUI()
|
|
{
|
|
midButtonStyle = new GUIStyle(GUI.skin.button);
|
|
midButtonStyle.margin = new RectOffset(0, 0, midButtonStyle.margin.top, midButtonStyle.margin.bottom);
|
|
midButtonStyle.padding = new RectOffset(3, 3, midButtonStyle.padding.top, midButtonStyle.padding.bottom);
|
|
|
|
leftButtonStyle = new GUIStyle(midButtonStyle);
|
|
leftButtonStyle.contentOffset = new Vector2(-leftButtonStyle.border.left * 0.5f, 0f);
|
|
rightButtonStyle = new GUIStyle(midButtonStyle);
|
|
rightButtonStyle.contentOffset = new Vector2(rightButtonStyle.border.right * 0.5f, 0f);
|
|
|
|
boxStyle = new GUIStyle(GUI.skin.GetStyle("box"));
|
|
boxStyle.normal.background = DreamteckEditorGUI.blankImage;
|
|
boxStyle.margin = new RectOffset(0, 0, 0, 2);
|
|
|
|
defaultButton = new GUIStyle(GUI.skin.GetStyle("button"));
|
|
_whiteBox = new GUIStyle(GUI.skin.GetStyle("box"));
|
|
_whiteBox.normal.background = white;
|
|
_defaultField = new GUIStyle(GUI.skin.GetStyle("textfield"));
|
|
_defaultField.normal.background = white;
|
|
_defaultField.normal.textColor = Color.white;
|
|
defaultField.alignment = TextAnchor.MiddleLeft;
|
|
_smallField = new GUIStyle(GUI.skin.GetStyle("textfield"));
|
|
_smallField.normal.background = white;
|
|
_smallField.normal.textColor = Color.white;
|
|
_smallField.alignment = TextAnchor.MiddleLeft;
|
|
_smallField.clipping = TextClipping.Clip;
|
|
labelText = new GUIStyle(GUI.skin.GetStyle("label"));
|
|
labelText.fontStyle = FontStyle.Bold;
|
|
labelText.alignment = TextAnchor.MiddleRight;
|
|
labelText.normal.textColor = Color.white;
|
|
dropdownItem = new GUIStyle(GUI.skin.GetStyle("button"));
|
|
dropdownItem.normal.background = white;
|
|
dropdownItem.normal.textColor = Color.white;
|
|
dropdownItem.alignment = TextAnchor.MiddleLeft;
|
|
bigButton = new GUIStyle(GUI.skin.GetStyle("button"));
|
|
bigButton.fontStyle = FontStyle.Bold;
|
|
bigButton.normal.textColor = buttonContentColor;
|
|
bigButtonSelected = new GUIStyle(GUI.skin.GetStyle("button"));
|
|
bigButtonSelected.fontStyle = FontStyle.Bold;
|
|
buttonContentColor = defaultButton.normal.textColor;
|
|
//If the button text color is too dark, generate a brightened version
|
|
float avg = (buttonContentColor.r + buttonContentColor.g + buttonContentColor.b) / 3f;
|
|
if (avg <= 0.2f) buttonContentColor = new Color(0.2f, 0.2f, 0.2f);
|
|
Rescale();
|
|
}
|
|
|
|
public static void SetHighlightColors(Color background, Color content)
|
|
{
|
|
highLightBGColor = background;
|
|
highlightContentColor = content;
|
|
}
|
|
|
|
public static bool LeftButton(GUIContent content, bool selected)
|
|
{
|
|
bool clicked = false;
|
|
Rect rect = ButtonBegin(selected, leftButtonStyle);
|
|
if (GUI.Button(new Rect(0, 0, rect.width + leftButtonStyle.border.right, rect.height), content, leftButtonStyle)) clicked = true;
|
|
ButtonEnd();
|
|
return clicked;
|
|
}
|
|
|
|
public static bool MidButton(GUIContent content, bool selected)
|
|
{
|
|
bool clicked = false;
|
|
Rect rect = ButtonBegin(selected, midButtonStyle);
|
|
if (GUI.Button(new Rect(-midButtonStyle.border.left, 0, rect.width + midButtonStyle.border.left + midButtonStyle.border.right, rect.height), content, midButtonStyle)) clicked = true;
|
|
ButtonEnd();
|
|
return clicked;
|
|
}
|
|
|
|
public static bool RightButton(GUIContent content, bool selected)
|
|
{
|
|
bool clicked = false;
|
|
Rect rect = ButtonBegin(selected, rightButtonStyle);
|
|
if (GUI.Button(new Rect(-rightButtonStyle.border.left, 0, rect.width + rightButtonStyle.border.left, rect.height), content, rightButtonStyle)) clicked = true;
|
|
ButtonEnd();
|
|
return clicked;
|
|
}
|
|
|
|
static Rect ButtonBegin(bool selected, GUIStyle style)
|
|
{
|
|
previousContentColor = GUI.contentColor;
|
|
previousBackgroundColor = GUI.backgroundColor;
|
|
GUI.contentColor = style.normal.textColor;
|
|
if (selected)
|
|
{
|
|
GUI.backgroundColor = highLightBGColor;
|
|
GUI.contentColor = highlightContentColor;
|
|
}
|
|
Rect rect = GUILayoutUtility.GetRect(30f, 22f);
|
|
GUI.BeginGroup(rect);
|
|
return rect;
|
|
}
|
|
|
|
public static void ButtonEnd()
|
|
{
|
|
GUI.EndGroup();
|
|
GUI.contentColor = previousContentColor;
|
|
GUI.backgroundColor = previousBackgroundColor;
|
|
}
|
|
|
|
public static int ButtonRibbon(GUIContent[] contents, float buttonWidth, int highLighted = -1)
|
|
{
|
|
int selected = -1;
|
|
float width = contents.Length * buttonWidth;
|
|
EditorGUILayout.BeginHorizontal(GUILayout.Width(width));
|
|
for (int i = 0; i < contents.Length; i++)
|
|
{
|
|
if (i == 0)
|
|
{
|
|
if (LeftButton(contents[i], highLighted == i)) selected = i;
|
|
}
|
|
else if (i == contents.Length - 1)
|
|
{
|
|
if(RightButton(contents[i], highLighted == i)) selected = i;
|
|
}
|
|
else
|
|
{
|
|
if(MidButton(contents[i], highLighted == i)) selected = i;
|
|
}
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
return selected;
|
|
}
|
|
|
|
|
|
public static void BeginContainerBox(ref bool open, string name)
|
|
{
|
|
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
|
EditorGUI.indentLevel++;
|
|
GUI.color = new Color(1f, 1f, 1f, 0.7f);
|
|
open = Foldout(open, name, true);
|
|
GUI.color = Color.white;
|
|
EditorGUI.indentLevel--;
|
|
EditorGUILayout.Space();
|
|
}
|
|
|
|
public static void EndContainerBox()
|
|
{
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
|
|
public static bool Foldout(bool foldout, GUIContent content, bool toggleOnLabelClick)
|
|
{
|
|
Rect position = GUILayoutUtility.GetRect(40f, 40f, 16f, 16f, EditorStyles.foldout);
|
|
return EditorGUI.Foldout(position, foldout, content, toggleOnLabelClick, EditorStyles.foldout);
|
|
}
|
|
|
|
public static bool Foldout(bool foldout, string content, bool toggleOnLabelClick)
|
|
{
|
|
return Foldout(foldout, new GUIContent(content), toggleOnLabelClick);
|
|
}
|
|
|
|
private static void Rescale()
|
|
{
|
|
defaultField.padding = new RectOffset(Mathf.RoundToInt(5 * scale), Mathf.RoundToInt(5 * scale), Mathf.RoundToInt(5 * scale), Mathf.RoundToInt(5 * scale));
|
|
smallField.padding = new RectOffset(Mathf.RoundToInt(2 * scale), Mathf.RoundToInt(2 * scale), Mathf.RoundToInt(2 * scale), Mathf.RoundToInt(2 * scale));
|
|
dropdownItem.padding = new RectOffset(Mathf.RoundToInt(10 * scale), 0, 0, 0);
|
|
bigButton.padding = new RectOffset(Mathf.RoundToInt(3*scale), Mathf.RoundToInt(3 * scale), Mathf.RoundToInt(3 * scale), Mathf.RoundToInt(3 * scale));
|
|
bigButtonSelected.normal.textColor = new Color(0.95f, 0.95f, 0.95f);
|
|
bigButton.padding = new RectOffset(Mathf.RoundToInt(4 * scale), Mathf.RoundToInt(4 * scale), Mathf.RoundToInt(4 * scale), Mathf.RoundToInt(4 * scale));
|
|
bigButton.fontSize = Mathf.RoundToInt(30 * scale);
|
|
bigButtonSelected.fontSize = Mathf.RoundToInt(30 * scale);
|
|
defaultButton.fontSize = Mathf.RoundToInt(14 * scale);
|
|
dropdownItem.fontSize = Mathf.RoundToInt(12 * scale);
|
|
labelText.fontSize = Mathf.RoundToInt(12 * scale);
|
|
defaultField.fontSize = Mathf.RoundToInt(14 * scale);
|
|
smallField.fontSize = Mathf.RoundToInt(11 * scale);
|
|
}
|
|
|
|
public static void SetScale(float s)
|
|
{
|
|
if(s != scale)
|
|
{
|
|
scale = s;
|
|
Rescale();
|
|
} scale = s;
|
|
}
|
|
|
|
public static bool EditorLayoutSelectableButton(GUIContent content, bool active = true, bool selected = false, params GUILayoutOption[] options)
|
|
{
|
|
Color prevColor = GUI.color;
|
|
Color prevContentColor = GUI.contentColor;
|
|
Color prevBackgroundColor = GUI.backgroundColor;
|
|
GUIStyle selectedStyle = GUI.skin.button;
|
|
if (!active) GUI.color = inactiveColor;
|
|
else
|
|
{
|
|
GUI.color = activeColor;
|
|
if (selected)
|
|
{
|
|
GUI.backgroundColor = highLightBGColor;
|
|
GUI.contentColor = highlightContentColor;
|
|
selectedStyle = new GUIStyle(selectedStyle);
|
|
selectedStyle.normal.textColor = Color.white;
|
|
selectedStyle.hover.textColor = Color.white;
|
|
selectedStyle.active.textColor = Color.white;
|
|
} else GUI.contentColor = buttonContentColor;
|
|
}
|
|
bool clicked = GUILayout.Button(content, selectedStyle, options);
|
|
GUI.color = prevColor;
|
|
GUI.contentColor = prevContentColor;
|
|
GUI.backgroundColor = prevBackgroundColor;
|
|
return clicked && active;
|
|
}
|
|
private static string CleanStringForFloat(string input)
|
|
{
|
|
if (Regex.Match(input, @"^-?[0-9]*(?:\.[0-9]*)?$").Success)
|
|
return input;
|
|
else
|
|
{
|
|
return "0";
|
|
}
|
|
}
|
|
|
|
private static void HandleControlsCount() {
|
|
if (controlIndex >= controlStates.Length)
|
|
{
|
|
bool[] newStates = new bool[controlStates.Length + 1];
|
|
controlStates.CopyTo(newStates, 0);
|
|
controlStates = newStates;
|
|
|
|
string[] newContents = new string[controlStates.Length + 1];
|
|
floatFieldContents.CopyTo(newContents, 0);
|
|
floatFieldContents = newContents;
|
|
}
|
|
}
|
|
|
|
#if DREAMTECK_SPLINES
|
|
public static double ScreenPointToSplinePercent(SplineComputer computer, Vector2 screenPoint)
|
|
{
|
|
SplinePoint[] points = computer.GetPoints();
|
|
float closestDistance = (screenPoint - HandleUtility.WorldToGUIPoint(points[0].position)).sqrMagnitude;
|
|
double closestPercent = 0.0;
|
|
double add = computer.moveStep;
|
|
if (computer.type == Spline.Type.Linear) add /= 2f;
|
|
int count = 0;
|
|
for (double i = add; i < 1.0; i += add)
|
|
{
|
|
SplineSample result = computer.Evaluate(i);
|
|
Vector2 point = HandleUtility.WorldToGUIPoint(result.position);
|
|
float dist = (point - screenPoint).sqrMagnitude;
|
|
if (dist < closestDistance)
|
|
{
|
|
closestDistance = dist;
|
|
closestPercent = i;
|
|
}
|
|
count++;
|
|
}
|
|
return closestPercent;
|
|
}
|
|
#endif
|
|
}
|
|
}
|