You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
342 lines
16 KiB
C#
342 lines
16 KiB
C#
using System;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace FluffyGroomingTool {
|
|
[Serializable]
|
|
public class PainterLayersUI {
|
|
private static readonly string EDIT_LAYER_CONTROL_NAME = "EDIT_LAYER_CONTROL_NAME";
|
|
private static readonly string EDIT_LAYER_CONTROL_NAME_UNFOCUSED = "EDIT_LAYER_CONTROL_NAME_UNFOCUSED";
|
|
private GUIStyle[] headerStyles;
|
|
private GUIStyle[] headerStylesTop;
|
|
private GUIStyle _buttonStyle;
|
|
private GUIStyle _buttonWithPaddingStyle;
|
|
internal GUIStyle trashButtonStyle;
|
|
internal GUIStyle duplicateButtonStyle;
|
|
internal GUIStyle editNameButtonStyle;
|
|
internal GUIStyle hideLayerOnStyle;
|
|
internal GUIStyle hideLayerOffStyle;
|
|
private GUIStyle headerText;
|
|
private GUIStyle paddingStyle;
|
|
private Texture2D arrowSide;
|
|
private Texture2D arrowDown;
|
|
internal Color32[] colors;
|
|
private static Color layersUITextColor = new Color(1, 1, 1, 0.9f);
|
|
private GUIStyle invisibleButtonStyle = new GUIStyle();
|
|
|
|
public GUIStyle buttonStyle {
|
|
get {
|
|
createStyles();
|
|
return _buttonStyle;
|
|
}
|
|
}
|
|
|
|
public void createStyles() {
|
|
if (_buttonStyle == null) {
|
|
headerStyles = new GUIStyle[5];
|
|
headerStyles[0] = createPanelStyle("bg_box_cyan");
|
|
headerStyles[1] = createPanelStyle("bg_box_blue");
|
|
headerStyles[2] = createPanelStyle("bg_box_pink");
|
|
headerStyles[3] = createPanelStyle("bg_box_orange");
|
|
headerStyles[4] = createPanelStyle("bg_box_green");
|
|
|
|
headerStylesTop = new GUIStyle[5];
|
|
headerStylesTop[0] = createTopPanelStyle("header_cyan");
|
|
headerStylesTop[1] = createTopPanelStyle("header_blue");
|
|
headerStylesTop[2] = createTopPanelStyle("header_pink");
|
|
headerStylesTop[3] = createTopPanelStyle("header_orange");
|
|
headerStylesTop[4] = createTopPanelStyle("header_green");
|
|
|
|
_buttonStyle = createButtonStyle("bg_button", "bg_button_hover");
|
|
_buttonStyle.richText = true;
|
|
_buttonWithPaddingStyle = createButtonStyle("bg_button", "bg_button_hover");
|
|
_buttonWithPaddingStyle.richText = true;
|
|
_buttonWithPaddingStyle.padding = new RectOffset(32, 16, 8, 8);
|
|
trashButtonStyle = createButtonStyle("ic_trash", "ic_trash_hover", 3);
|
|
duplicateButtonStyle = createButtonStyle("duplicate", "duplicate_hoover");
|
|
editNameButtonStyle = createButtonStyle("edit", "edit_hoover");
|
|
hideLayerOnStyle = createButtonStyle("HideLayerOn", "HideLayerOnHover");
|
|
hideLayerOffStyle = createButtonStyle("HideLayerOff", "HideLayerOffHover");
|
|
|
|
headerText = new GUIStyle(GUI.skin.label) {
|
|
fontStyle = FontStyle.Bold, fontSize = 12, normal = {textColor = layersUITextColor},
|
|
richText = true
|
|
};
|
|
paddingStyle = new GUIStyle {padding = new RectOffset(15, 16, 0, 17), margin = new RectOffset(0, 0, -10, 0)};
|
|
colors = new[] {
|
|
new Color32(90, 211, 172, 255),
|
|
new Color32(55, 210, 232, 255),
|
|
new Color32(207, 115, 229, 255),
|
|
new Color32(255, 133, 45, 255),
|
|
new Color32(153, 220, 81, 255)
|
|
};
|
|
}
|
|
|
|
if (arrowSide == null) {
|
|
arrowSide = Resources.Load<Texture2D>("ic_arrow_side");
|
|
arrowDown = Resources.Load<Texture2D>("ic_arrow_down");
|
|
}
|
|
}
|
|
|
|
public static GUIStyle createButtonStyle(string normal, string hover, int border = 5) {
|
|
return new GUIStyle(GUI.skin.label) {
|
|
border = new RectOffset(border, border, border, border),
|
|
normal = {background = Resources.Load<Texture2D>(normal), textColor = layersUITextColor},
|
|
hover = {background = Resources.Load<Texture2D>(hover), textColor = layersUITextColor},
|
|
fontSize = 12,
|
|
padding = new RectOffset(16, 16, 5, 7),
|
|
margin = new RectOffset(17, 17, 0, 0),
|
|
fontStyle = FontStyle.Bold,
|
|
alignment = TextAnchor.MiddleCenter
|
|
};
|
|
}
|
|
|
|
public GUIStyle createTopPanelStyle(String textureName) {
|
|
var headerStyle = new GUIStyle(GUI.skin.label);
|
|
headerStyle.border = new RectOffset(20, 20, 20, 10);
|
|
headerStyle.padding = new RectOffset(28, 16, 6, 6);
|
|
headerStyle.margin = new RectOffset(2, 2, -1, -2);
|
|
headerStyle.normal.background = Resources.Load<Texture2D>(textureName);
|
|
return headerStyle;
|
|
}
|
|
|
|
public GUIStyle createPanelStyle(String textureName) {
|
|
var headerStyle = new GUIStyle(GUI.skin.label);
|
|
headerStyle.border = new RectOffset(20, 20, 20, 20);
|
|
headerStyle.padding = new RectOffset(0, 0, 0, 0);
|
|
headerStyle.normal.background = Resources.Load<Texture2D>(textureName);
|
|
return headerStyle;
|
|
}
|
|
|
|
private bool isExpanded = true;
|
|
|
|
public bool isDrawHeader() {
|
|
isExpanded = EditorGUILayout.Foldout(isExpanded, "Fur Layers");
|
|
if (isExpanded) GUILayout.Space(4);
|
|
return isExpanded;
|
|
}
|
|
|
|
private bool editLayerName;
|
|
private bool editLayerNameUnfocused;
|
|
|
|
public void drawLayerHeadingUI(FurCreator furCreator, int index, float width) {
|
|
createStyles();
|
|
|
|
bool isActiveLayer = furCreator.groomContainer.activeLayerIndex == index;
|
|
var isHidden = furCreator.groomContainer.layers[index].isHidden;
|
|
var hideLayerStyle = isHidden ? hideLayerOnStyle : hideLayerOffStyle;
|
|
var layersLength = furCreator.groomContainer.layers.Length;
|
|
if (isActiveLayer) {
|
|
GUILayout.BeginVertical(headerStyles[index % 5]);
|
|
GUILayout.BeginHorizontal(headerStylesTop[index % 5]);
|
|
drawHeadersText(furCreator, index, isHidden);
|
|
|
|
GUILayout.EndHorizontal();
|
|
drawArrowTexture(arrowDown);
|
|
|
|
var trashRect = createTrashRectFocused(layersLength);
|
|
if (layersLength > 1) {
|
|
if (GUI.Button(trashRect, new GUIContent("", "Delete the layer."), trashButtonStyle)) {
|
|
furCreator.deleteLayer(index);
|
|
}
|
|
}
|
|
|
|
var toggleVisibilityRect = crateToggleVisibilityRect(trashRect);
|
|
if (GUI.Button(toggleVisibilityRect, new GUIContent("", "Toggle layer hidden state."), hideLayerStyle)) {
|
|
furCreator.hideOrShowLayer(index);
|
|
}
|
|
|
|
var duplicateRect = crateDuplicateRect(toggleVisibilityRect);
|
|
if (GUI.Button(duplicateRect, new GUIContent("", "Duplicate the layer."), duplicateButtonStyle)) {
|
|
furCreator.duplicateLayer(index);
|
|
}
|
|
|
|
var editNameRect = crateDuplicateRect(duplicateRect);
|
|
if (GUI.Button(editNameRect, new GUIContent("", "Edit the layer name."), editNameButtonStyle)) {
|
|
editLayerName = true;
|
|
EditorGUI.FocusTextInControl(EDIT_LAYER_CONTROL_NAME);
|
|
}
|
|
|
|
GUILayout.BeginVertical(paddingStyle);
|
|
GUILayout.Space(5);
|
|
}
|
|
else {
|
|
GUILayout.Space(0); //We just need this in order for getLastRect to work.
|
|
var currentColor = colors[index % 5];
|
|
if (!EditorGUIUtility.isProSkin) {
|
|
currentColor = Color.black;
|
|
currentColor.a = 200;
|
|
}
|
|
|
|
_buttonWithPaddingStyle.normal.textColor = currentColor;
|
|
_buttonWithPaddingStyle.hover.textColor = currentColor;
|
|
_buttonWithPaddingStyle.alignment = TextAnchor.MiddleLeft;
|
|
|
|
GUILayout.Space(0); //Needed in order to call GUILayoutUtility.GetLastRect()
|
|
//This is actually the trash can button, but since Unity UI passed the click events inverted we need a transparent button here.
|
|
var invisibleButtonRect = createInvisibleButtonRect(width);
|
|
|
|
if (layersLength > 1) {
|
|
if (GUI.Button(invisibleButtonRect, "", invisibleButtonStyle)) {
|
|
furCreator.deleteLayer(index);
|
|
}
|
|
}
|
|
|
|
invisibleButtonRect.position = new Vector2(invisibleButtonRect.position.x - 30f, invisibleButtonRect.position.y);
|
|
if (GUI.Button(invisibleButtonRect, "", invisibleButtonStyle)) {
|
|
furCreator.hideOrShowLayer(index);
|
|
}
|
|
|
|
invisibleButtonRect.position = new Vector2(invisibleButtonRect.position.x - 30f, invisibleButtonRect.position.y);
|
|
if (GUI.Button(invisibleButtonRect, "", invisibleButtonStyle)) {
|
|
furCreator.duplicateLayer(index);
|
|
}
|
|
|
|
invisibleButtonRect.position = new Vector2(invisibleButtonRect.position.x - 30f, invisibleButtonRect.position.y);
|
|
if (GUI.Button(invisibleButtonRect, "", invisibleButtonStyle)) {
|
|
editLayerNameUnfocused = true;
|
|
GUI.FocusControl(EDIT_LAYER_CONTROL_NAME_UNFOCUSED);
|
|
}
|
|
|
|
initLayerName(furCreator, index);
|
|
if (GUILayout.Button(getLayerNameText(furCreator, index, isHidden), _buttonWithPaddingStyle)) {
|
|
if (!editLayerNameUnfocused) {
|
|
furCreator.setActiveLayerIndex(index);
|
|
}
|
|
}
|
|
|
|
if (shouldHideLayerNameEdit()) {
|
|
editLayerNameUnfocused = false;
|
|
}
|
|
|
|
var lastRect = GUILayoutUtility.GetLastRect();
|
|
GUI.SetNextControlName(EDIT_LAYER_CONTROL_NAME_UNFOCUSED);
|
|
furCreator.FurRenderer.furContainer.layerStrandsList[index].layerName = GUI.TextField(
|
|
new Rect(lastRect.x + 28, lastRect.y + 7, editLayerNameUnfocused ? 250 : 0, 20),
|
|
furCreator.FurRenderer.furContainer.layerStrandsList[index].layerName);
|
|
drawArrowTexture(arrowSide);
|
|
var trashRect = createTrashRect();
|
|
if (layersLength > 1) {
|
|
GUI.Button(trashRect, "", trashButtonStyle);
|
|
}
|
|
|
|
var toggleVisibilityRect = crateToggleVisibilityRect(trashRect);
|
|
GUI.Button(toggleVisibilityRect, new GUIContent("", "Toggle layer hidden state."), hideLayerStyle);
|
|
var duplicateRect = crateDuplicateRect(toggleVisibilityRect);
|
|
GUI.Button(duplicateRect, new GUIContent("", "Duplicate the layer."), duplicateButtonStyle);
|
|
var editNameRect = crateDuplicateRect(duplicateRect);
|
|
GUI.Button(editNameRect, new GUIContent("", "Edit the layer name."), editNameButtonStyle);
|
|
}
|
|
|
|
GUILayout.Space(4);
|
|
}
|
|
|
|
private static string getLayerNameText(FurCreator furCreator, int index, bool isHidden) {
|
|
return furCreator.FurRenderer.furContainer.layerStrandsList[index].layerName +
|
|
(isHidden ? " <color=#FF002E>(HIDDEN)</color>" : "");
|
|
}
|
|
|
|
private void drawHeadersText(FurCreator furCreator, int index, bool isHidden) {
|
|
headerText.alignment = TextAnchor.MiddleLeft;
|
|
if (shouldHideLayerNameEdit()) {
|
|
editLayerName = false;
|
|
}
|
|
|
|
if (index < furCreator.FurRenderer.furContainer.layerStrandsList.Length) {
|
|
initLayerName(furCreator, index);
|
|
GUI.SetNextControlName(EDIT_LAYER_CONTROL_NAME);
|
|
EditorGUI.BeginChangeCheck();
|
|
furCreator.FurRenderer.furContainer.layerStrandsList[index].layerName = EditorGUILayout.TextField(
|
|
furCreator.FurRenderer.furContainer.layerStrandsList[index].layerName,
|
|
GUILayout.Width(editLayerName ? 250 : 0)
|
|
);
|
|
if (EditorGUI.EndChangeCheck()) {
|
|
EditorUtility.SetDirty(furCreator.FurRenderer.furContainer);
|
|
}
|
|
|
|
addLayerName(furCreator.FurRenderer.furContainer.layerStrandsList[index].layerName, isHidden);
|
|
}
|
|
else {
|
|
addLayerName("Layer " + (index + 1), isHidden);
|
|
}
|
|
}
|
|
|
|
private static void initLayerName(FurCreator furCreator, int index) {
|
|
if (string.IsNullOrEmpty(furCreator.FurRenderer.furContainer.layerStrandsList[index].layerName)) {
|
|
furCreator.FurRenderer.furContainer.layerStrandsList[index].layerName = "Layer " + (index + 1);
|
|
}
|
|
}
|
|
|
|
private void addLayerName(string layerName, bool isHidden) {
|
|
GUILayout.Label(
|
|
layerName + " (Active)" +
|
|
(isHidden ? " <color=#FF002E>(HIDDEN)</color>" : ""), headerText,
|
|
GUILayout.Width(editLayerName ? 0 : 250));
|
|
}
|
|
|
|
private bool shouldHideLayerNameEdit() {
|
|
return Event.current.type == EventType.MouseDown ||
|
|
Event.current.type == EventType.KeyUp && Event.current.keyCode == KeyCode.Return;
|
|
}
|
|
|
|
|
|
private static Rect crateToggleVisibilityRect(Rect currentRectPosition) {
|
|
currentRectPosition.position = new Vector2(currentRectPosition.position.x - 27f, currentRectPosition.position.y + 1);
|
|
currentRectPosition.width = 26;
|
|
currentRectPosition.height = 26;
|
|
return currentRectPosition;
|
|
}
|
|
|
|
private static Rect crateDuplicateRect(Rect currentRectPosition) {
|
|
currentRectPosition.position = new Vector2(currentRectPosition.position.x - 30f, currentRectPosition.position.y);
|
|
|
|
return currentRectPosition;
|
|
}
|
|
|
|
private static Rect createTrashRect() {
|
|
var lastRect = GUILayoutUtility.GetLastRect();
|
|
return new Rect(lastRect.width - 14, lastRect.y + 1, 28, 28);
|
|
}
|
|
|
|
private Rect createTrashRectFocused(int layersLength) {
|
|
var lastRect = GUILayoutUtility.GetLastRect();
|
|
|
|
return new Rect(layersLength == 1 ? lastRect.width + 18 : lastRect.width - 12, lastRect.y + 1, 28, 28);
|
|
}
|
|
|
|
private static Rect createInvisibleButtonRect(float width) {
|
|
var lastRect = GUILayoutUtility.GetLastRect();
|
|
return new Rect(width - 64, lastRect.y + 10, 32, 32);
|
|
}
|
|
|
|
public void drawAddLayerButton(FurCreator furCreator) {
|
|
var normalTextColor = Color.white;
|
|
if (!EditorGUIUtility.isProSkin) {
|
|
normalTextColor = Color.black;
|
|
}
|
|
|
|
normalTextColor.a = 0.9f;
|
|
_buttonStyle.normal.textColor = normalTextColor;
|
|
_buttonStyle.hover.textColor = normalTextColor;
|
|
_buttonStyle.alignment = TextAnchor.MiddleCenter;
|
|
GUILayout.Space(1);
|
|
if (GUILayout.Button(new GUIContent("Add New Layer", "Add a new layer with a separate groom."), _buttonStyle)) {
|
|
furCreator.addLayer();
|
|
}
|
|
}
|
|
|
|
private void drawArrowTexture(Texture2D texture) {
|
|
var lastRect = GUILayoutUtility.GetLastRect();
|
|
Color guiColor = GUI.color;
|
|
GUI.color = Color.clear;
|
|
EditorGUI.DrawTextureTransparent(new Rect(lastRect.x + 15, lastRect.y + 10, 12, 12), texture);
|
|
GUI.color = guiColor;
|
|
}
|
|
|
|
public void endLayout() {
|
|
GUILayout.EndVertical();
|
|
GUILayout.EndVertical();
|
|
GUILayout.Space(10);
|
|
}
|
|
}
|
|
} |