933 lines
31 KiB
C#
933 lines
31 KiB
C#
#if UNITY_EDITOR
|
|
using System;
|
|
using System.Globalization;
|
|
using System.Text;
|
|
using UnityEditor;
|
|
using UnityEditorInternal;
|
|
using UnityEngine;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace NWH.NUI
|
|
{
|
|
/// <summary>
|
|
/// A small Editor GUI library designed as a replacement for EditorGUILayout.
|
|
/// </summary>
|
|
public class NUIDrawer
|
|
{
|
|
public enum DrawerType
|
|
{
|
|
Property,
|
|
Editor,
|
|
}
|
|
|
|
public string documentationBaseURL = "http://nwhvehiclephysics.com/doku.php/";
|
|
|
|
public Rect positionRect = new Rect(-1, -1, -1, -1);
|
|
public SerializedObject serializedObject;
|
|
public SerializedProperty serializedProperty;
|
|
public float totalHeight;
|
|
|
|
private readonly float sidePadding = 6f;
|
|
private GUIStyle bgStyle = new GUIStyle();
|
|
private readonly GUIStyle unitStyle = new GUIStyle();
|
|
private string _cachedKey;
|
|
private DrawerType _drawerType = DrawerType.Property;
|
|
private Rect customPositionRect = new Rect(-1, -1, -1, -1);
|
|
|
|
|
|
private void InitializeGUIElements()
|
|
{
|
|
// Background style
|
|
bgStyle = EditorStyles.helpBox;
|
|
|
|
// Initialize styles
|
|
unitStyle.fontSize = 9;
|
|
unitStyle.alignment = TextAnchor.MiddleRight;
|
|
unitStyle.normal.textColor = Color.grey;
|
|
}
|
|
|
|
|
|
public void UpdateCachedKey()
|
|
{
|
|
_cachedKey = GenerateKey();
|
|
}
|
|
|
|
|
|
public static string GenerateKey(SerializedProperty property)
|
|
{
|
|
if (property == null || property.serializedObject == null) return "null";
|
|
return GenerateKey(property.serializedObject) + property.propertyPath;
|
|
}
|
|
|
|
|
|
public static string GenerateKey(SerializedObject obj)
|
|
{
|
|
return obj.targetObject.GetInstanceID().ToString();
|
|
}
|
|
|
|
|
|
public static string GenerateKey(Object obj)
|
|
{
|
|
return obj.GetInstanceID().ToString();
|
|
}
|
|
|
|
|
|
public static int GetPropertyDepth(SerializedProperty property)
|
|
{
|
|
return property.propertyPath.Split('.').Length - 1;
|
|
}
|
|
|
|
|
|
public static void SetTabIndex(string tabName, int value)
|
|
{
|
|
//EditorCache.SetCachedValue("tabIndex", value, tabName);
|
|
EditorPrefs.SetInt("NWH" + tabName, value);
|
|
}
|
|
|
|
|
|
public void AdvancePosition(float height = NUISettings.fieldHeight)
|
|
{
|
|
positionRect = new Rect(positionRect.x, positionRect.y + height, positionRect.width,
|
|
NUISettings.fieldHeight);
|
|
totalHeight += height;
|
|
}
|
|
|
|
|
|
|
|
public void BeginEditor(SerializedObject serializedObject)
|
|
{
|
|
_drawerType = DrawerType.Editor;
|
|
this.serializedObject = serializedObject;
|
|
serializedProperty = null;
|
|
_cachedKey = GenerateKey();
|
|
|
|
if (serializedObject == null)
|
|
{
|
|
Debug.LogError("Cannot draw editor for null serializedObject.");
|
|
return;
|
|
}
|
|
|
|
serializedObject.Update();
|
|
|
|
if (customPositionRect.x < 0 && customPositionRect.width < 0)
|
|
{
|
|
positionRect = EditorGUILayout.GetControlRect();
|
|
positionRect.x = positionRect.x - 3;
|
|
positionRect.width = positionRect.width + 6;
|
|
}
|
|
else
|
|
{
|
|
positionRect = customPositionRect;
|
|
}
|
|
|
|
totalHeight = 0;
|
|
InitializeGUIElements();
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
DrawBackgroundRect(new Rect(positionRect.x, positionRect.y, positionRect.width, GetHeight()));
|
|
}
|
|
|
|
|
|
public void BeginProperty(Rect position, SerializedProperty property, GUIContent label)
|
|
{
|
|
if (property == null)
|
|
{
|
|
Debug.LogError("Cannot draw property drawer for null property.");
|
|
return;
|
|
}
|
|
|
|
_drawerType = DrawerType.Property;
|
|
serializedProperty = property;
|
|
serializedObject = property.serializedObject;
|
|
_cachedKey = GenerateKey();
|
|
|
|
totalHeight = 0;
|
|
positionRect = position;
|
|
|
|
bool guiWasEnabled = true;
|
|
if (EditorCache.GetGuiWasEnabledCValue(GenerateKey(), ref guiWasEnabled))
|
|
{
|
|
GUI.enabled = guiWasEnabled;
|
|
}
|
|
|
|
InitializeGUIElements();
|
|
|
|
Rect totalRect = new Rect(positionRect.x, positionRect.y, positionRect.width, GetHeight());
|
|
DrawBackgroundRect(new Rect(positionRect.x, positionRect.y, positionRect.width, GetHeight()));
|
|
//EditorGUI.BeginProperty(totalRect, label, property);
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
}
|
|
|
|
|
|
public void BeginSubsection(string label)
|
|
{
|
|
Title(label);
|
|
IncreaseIndent();
|
|
}
|
|
|
|
|
|
public bool Button(string label, GUIStyle style = null)
|
|
{
|
|
Rect buttonRect = positionRect;
|
|
buttonRect.y += 2f;
|
|
buttonRect.height = NUISettings.fieldHeight - 4f;
|
|
|
|
GUIStyle buttonStyle = style != null ? new GUIStyle(style) : new GUIStyle(EditorStyles.miniButton);
|
|
buttonStyle.fixedHeight = buttonRect.height;
|
|
|
|
bool buttonState = GUI.Button(buttonRect, label, buttonStyle);
|
|
|
|
AdvancePosition(buttonRect.height + NUISettings.fieldSpacing);
|
|
return buttonState;
|
|
}
|
|
|
|
|
|
public void DecreaseIndent()
|
|
{
|
|
positionRect = new Rect(positionRect.x - 6, positionRect.y, positionRect.width + 6, positionRect.height);
|
|
}
|
|
|
|
|
|
public void DrawBackgroundRect(Rect rect)
|
|
{
|
|
if (rect.height < 2f)
|
|
{
|
|
return;
|
|
}
|
|
|
|
GUI.Box(rect, "", bgStyle);
|
|
Color bgColor = EditorGUIUtility.isProSkin
|
|
? new Color(1, 1, 1, 0.015f)
|
|
: new Color(1, 1, 1, 0.1f);
|
|
EditorGUI.DrawRect(rect, bgColor);
|
|
}
|
|
|
|
|
|
public void DrawEditorTexture(Rect rect, string path, ScaleMode scaleMode = ScaleMode.StretchToFill)
|
|
{
|
|
Texture2D tex = GetTexture(path);
|
|
if (tex != null)
|
|
{
|
|
DrawEditorTexture(rect, tex, scaleMode);
|
|
}
|
|
}
|
|
|
|
|
|
public void DrawEditorTexture(Rect rect, Texture2D texture, ScaleMode scaleMode = ScaleMode.StretchToFill)
|
|
{
|
|
if (texture != null)
|
|
{
|
|
GUI.DrawTexture(rect, texture, scaleMode);
|
|
}
|
|
}
|
|
|
|
|
|
public void EmbeddedObjectEditor<T>(Object obj, Rect rect, float leftMargin = 0) where T : NUIEditor
|
|
{
|
|
if (obj == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
NUIEditor editor = null;
|
|
string key = GenerateKey(obj);
|
|
EditorCache.GetNUIEditorCacheValue(key, ref editor);
|
|
T nuiEditor = editor as T;
|
|
|
|
if (nuiEditor == null)
|
|
{
|
|
nuiEditor = Editor.CreateEditor(obj) as T;
|
|
|
|
if (nuiEditor == null)
|
|
{
|
|
Debug.LogError("Failed to create scriptable object editor.");
|
|
return;
|
|
}
|
|
|
|
EditorCache.SetNUIEditorCacheValue(GenerateKey(obj), nuiEditor);
|
|
}
|
|
|
|
rect.y += 8;
|
|
|
|
if (nuiEditor != null)
|
|
{
|
|
Space();
|
|
nuiEditor.drawer.customPositionRect = positionRect;
|
|
nuiEditor.OnInspectorNUI();
|
|
|
|
float editorHeight = GetHeight(key);
|
|
GUILayout.Space(
|
|
-editorHeight); // Negate space that embedded editor has already added to prevent overly-large final editor
|
|
AdvancePosition(editorHeight);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Cannot draw null editor.");
|
|
}
|
|
|
|
UpdateCachedKey();
|
|
}
|
|
|
|
|
|
public void EndEditor(NUIEditor nuiEditor = null)
|
|
{
|
|
if (totalHeight > 32f)
|
|
{
|
|
totalHeight += 5; // Add padding if expanded
|
|
}
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
if (serializedObject.targetObject != null)
|
|
{
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
}
|
|
|
|
SetHeight(totalHeight);
|
|
GUILayout.Space(totalHeight);
|
|
}
|
|
|
|
|
|
public virtual void EndProperty()
|
|
{
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
if (totalHeight > 30f)
|
|
{
|
|
Space(6); // Add padding if expanded
|
|
}
|
|
|
|
bool wasEnabled = true;
|
|
EditorCache.GetGuiWasEnabledCValue(GenerateKey(), ref wasEnabled);
|
|
if (!GUI.enabled && wasEnabled)
|
|
{
|
|
EditorGUI.EndDisabledGroup();
|
|
}
|
|
|
|
SetHeight(totalHeight);
|
|
GUI.enabled = true;
|
|
}
|
|
|
|
|
|
public void EndSubsection()
|
|
{
|
|
DecreaseIndent();
|
|
Space();
|
|
}
|
|
|
|
public SerializedProperty FloatSlider(string propertyRelativeName, float min = 0, float max = 1, string leftLabel = "",
|
|
string rightLabel = "", bool showNumValue = true)
|
|
{
|
|
Debug.Assert(max > min);
|
|
|
|
SerializedProperty property = FindProperty(propertyRelativeName);
|
|
|
|
if (property == null)
|
|
{
|
|
Debug.LogWarning($"Could not find property '{propertyRelativeName}'");
|
|
return null;
|
|
}
|
|
|
|
EditorGUI.LabelField(positionRect,
|
|
CultureInfo.CurrentCulture.TextInfo.ToTitleCase(AddSpacesToSentence(propertyRelativeName, true)));
|
|
|
|
Rect sliderRect = new Rect(positionRect);
|
|
float leftOffset = sliderRect.width * 0.4f;
|
|
sliderRect.x += leftOffset;
|
|
sliderRect.width -= leftOffset;
|
|
|
|
if (showNumValue)
|
|
{
|
|
property.floatValue = EditorGUI.Slider(sliderRect, property.floatValue, min, max);
|
|
}
|
|
else
|
|
{
|
|
property.floatValue = GUI.HorizontalSlider(sliderRect, property.floatValue, min, max);
|
|
}
|
|
|
|
float midValue = (min + max) / 2f;
|
|
float range = (max - min);
|
|
float snapZone = range / 90f;
|
|
float propertyValue = property.floatValue;
|
|
if (propertyValue > midValue - snapZone && propertyValue < midValue + snapZone)
|
|
{
|
|
property.floatValue = midValue;
|
|
}
|
|
|
|
|
|
Rect legendRect = new Rect(sliderRect);
|
|
legendRect.y += 4;
|
|
|
|
if (showNumValue)
|
|
{
|
|
legendRect.width -= 53f;
|
|
}
|
|
EditorGUI.LabelField(legendRect, $"{leftLabel} <----> {rightLabel}", EditorStyles.centeredGreyMiniLabel);
|
|
|
|
AdvancePosition(NUISettings.fieldHeight + NUISettings.fieldSpacing);
|
|
|
|
return property;
|
|
}
|
|
|
|
public SerializedProperty Field(string propertyRelativeName, bool enabled = true, string unit = null,
|
|
string alternateLabel = null, float fieldHeight = -1, bool includeChildren = false)
|
|
{
|
|
SerializedProperty property = FindProperty(propertyRelativeName);
|
|
|
|
if (property == null)
|
|
{
|
|
Debug.LogWarning($"Could not find relative property '{propertyRelativeName}' on " +
|
|
$"'{serializedObject?.targetObject?.name}' > '{serializedProperty?.name}'");
|
|
return null;
|
|
}
|
|
|
|
property.isExpanded = true;
|
|
bool guiWasEnabled = GUI.enabled;
|
|
EditorGUI.BeginDisabledGroup(!enabled);
|
|
|
|
if (fieldHeight < 0)
|
|
{
|
|
fieldHeight = (int)EditorGUI.GetPropertyHeight(property, includeChildren);
|
|
}
|
|
|
|
Rect fieldRect = positionRect;
|
|
fieldRect.height = fieldHeight;
|
|
|
|
// Draw field
|
|
if (string.IsNullOrEmpty(alternateLabel))
|
|
{
|
|
EditorGUI.PropertyField(fieldRect, property, includeChildren);
|
|
}
|
|
else
|
|
{
|
|
EditorGUI.PropertyField(fieldRect, property, new GUIContent(alternateLabel), includeChildren);
|
|
}
|
|
|
|
// Draw unit
|
|
if (unit != null)
|
|
{
|
|
float unitRectWidth = 8f + unit.Length * 8f;
|
|
Rect unitRect = new Rect(fieldRect.x + fieldRect.width - unitRectWidth - 5, fieldRect.y,
|
|
unitRectWidth, fieldRect.height);
|
|
EditorGUI.LabelField(unitRect, new GUIContent(unit), unitStyle);
|
|
}
|
|
|
|
if (guiWasEnabled)
|
|
{
|
|
EditorGUI.EndDisabledGroup();
|
|
}
|
|
|
|
AdvancePosition(fieldHeight + NUISettings.fieldSpacing);
|
|
return property;
|
|
}
|
|
|
|
|
|
public void DrawDefaultEditor()
|
|
{
|
|
SerializedProperty prop = serializedObject.GetIterator();
|
|
if (prop.NextVisible(true))
|
|
{
|
|
do
|
|
{
|
|
if (prop.name == "m_Script")
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Field(prop.name);
|
|
AdvancePosition(EditorGUI.GetPropertyHeight(prop, true));
|
|
} while (prop.NextVisible(false));
|
|
}
|
|
}
|
|
|
|
|
|
public SerializedProperty FindProperty(string name)
|
|
{
|
|
return _drawerType == DrawerType.Property
|
|
? serializedProperty.FindPropertyRelative(name)
|
|
: serializedObject.FindProperty(name);
|
|
}
|
|
|
|
|
|
public string GenerateKey()
|
|
{
|
|
return _drawerType == DrawerType.Property ? GenerateKey(serializedProperty) : GenerateKey(serializedObject);
|
|
}
|
|
|
|
|
|
public float GetHeight()
|
|
{
|
|
return GetHeight(_cachedKey);
|
|
}
|
|
|
|
|
|
public float GetHeight(string key)
|
|
{
|
|
float height = 0;
|
|
EditorCache.GetHeightCacheValue(key, ref height);
|
|
return height <= 0 ? 1 : height;
|
|
}
|
|
|
|
|
|
public T GetObject<T>() where T : class
|
|
{
|
|
if (_drawerType == DrawerType.Property)
|
|
{
|
|
return SerializedPropertyHelper.GetTargetObjectOfProperty(serializedProperty) as T;
|
|
}
|
|
|
|
return serializedObject.targetObject as T;
|
|
}
|
|
|
|
|
|
public int GetTabIndex(string tabName)
|
|
{
|
|
return EditorPrefs.GetInt("NWH" + tabName, 0);
|
|
}
|
|
|
|
|
|
public Texture2D GetTexture(string resourcesPath)
|
|
{
|
|
Texture2D tex = null;
|
|
EditorCache.GetTexture2DCacheValue(resourcesPath, ref tex);
|
|
if (tex == null)
|
|
{
|
|
tex = Resources.Load(resourcesPath) as Texture2D;
|
|
if (tex == null)
|
|
{
|
|
Debug.LogError($"{resourcesPath} not found or not Texture2D.");
|
|
}
|
|
else
|
|
{
|
|
EditorCache.SetTexture2DCacheValue(resourcesPath, tex);
|
|
}
|
|
}
|
|
|
|
return tex;
|
|
}
|
|
|
|
|
|
public bool Header(string label, bool drawFoldoutButton = true)
|
|
{
|
|
label = AddSpacesToSentence(label, true);
|
|
|
|
Rect backgroundRect = new Rect(positionRect.x, positionRect.y, positionRect.width, 22);
|
|
|
|
GUIContent content = new GUIContent(label);
|
|
EditorStyles.label.CalcMinMaxWidth(content, out float minLabelWidth, out float maxLabelWidth);
|
|
|
|
#if UNITY_2019_3_OR_NEWER
|
|
Rect labelRect = new Rect(positionRect.x + NUISettings.textMargin + 15f, positionRect.y - 1, maxLabelWidth,
|
|
NUISettings.fieldHeight);
|
|
#else
|
|
Rect labelRect = new Rect(positionRect.x + NUISettings.textMargin + 15f, positionRect.y + 3, maxLabelWidth,
|
|
NUISettings.fieldHeight);
|
|
#endif
|
|
|
|
// If object, check if scriptable or normal
|
|
bool isScriptableObject = false;
|
|
if (_drawerType == DrawerType.Editor)
|
|
{
|
|
isScriptableObject = serializedObject.targetObject is ScriptableObject;
|
|
}
|
|
|
|
// Draw background
|
|
Color bgColor = _drawerType == DrawerType.Property ? NUISettings.propertyHeaderColor :
|
|
isScriptableObject ? NUISettings.scriptableObjectHeaderColor :
|
|
NUISettings.editorHeaderColor;
|
|
EditorGUI.DrawRect(backgroundRect, bgColor);
|
|
|
|
|
|
// Draw label
|
|
GUIStyle style = new GUIStyle(EditorStyles.label);
|
|
style.normal.textColor = Color.white;
|
|
EditorGUI.LabelField(labelRect, new GUIContent(label), style);
|
|
|
|
// Draw help link
|
|
Rect helpRect = new Rect(labelRect.x + labelRect.width + 5f, positionRect.y + 3, 16, 16);
|
|
DrawEditorTexture(helpRect, "NUI/help");
|
|
if (Event.current.type == EventType.MouseUp && helpRect.Contains(Event.current.mousePosition))
|
|
{
|
|
string fullTypeName = _drawerType == DrawerType.Property
|
|
? SerializedPropertyHelper.GetTargetObjectOfProperty(serializedProperty)
|
|
.GetType().FullName
|
|
: serializedObject.targetObject.GetType().FullName;
|
|
string objectPath = fullTypeName.Replace('.', '/');
|
|
Application.OpenURL($"{documentationBaseURL}/{objectPath}");
|
|
}
|
|
|
|
AdvancePosition();
|
|
|
|
// Apply padding
|
|
positionRect = new Rect(
|
|
positionRect.x + sidePadding,
|
|
positionRect.y,
|
|
positionRect.width - sidePadding * 2f,
|
|
positionRect.height);
|
|
|
|
if (_drawerType == DrawerType.Editor)
|
|
{
|
|
if (serializedObject.targetObject is ScriptableObject)
|
|
{
|
|
Info("This is a ScriptableObject. All changes are global.");
|
|
}
|
|
}
|
|
|
|
SetHeight(totalHeight);
|
|
return true;
|
|
}
|
|
|
|
|
|
public void HorizontalRuler(float thickness = 1f)
|
|
{
|
|
EditorGUI.DrawRect(new Rect(positionRect.x, positionRect.y + 2, positionRect.width, thickness),
|
|
EditorGUIUtility.isProSkin
|
|
? new Color(0.1f, 0.1f, 0.1f, 1f)
|
|
: new Color(0.5f, 0.5f, 0.5f, 1f));
|
|
AdvancePosition(thickness + 4);
|
|
}
|
|
|
|
|
|
public int HorizontalToolbar(string name, string[] texts, bool fillWidth = true, bool singleLine = false,
|
|
float targetButtonWidth = 80f, float buttonHeight = 18f)
|
|
{
|
|
float toolbarHeight = 0;
|
|
int tabIndex = GetTabIndex(name);
|
|
|
|
if (positionRect.width > 20f)
|
|
{
|
|
Rect initRect = positionRect;
|
|
initRect.x += 2f;
|
|
float rowHeight = buttonHeight;
|
|
int buttonCount = texts.Length;
|
|
float rowWidth = positionRect.width - 2f;
|
|
float singleLineWidth = buttonCount * targetButtonWidth;
|
|
int rowCount = singleLine ? 1 : rowWidth > 10 ? Mathf.CeilToInt(singleLineWidth / rowWidth) : 1;
|
|
int maxButtonsPerRow = Mathf.FloorToInt(rowWidth / targetButtonWidth);
|
|
int lastRowButtons = buttonCount - maxButtonsPerRow * (rowCount - 1);
|
|
toolbarHeight = rowCount * rowHeight;
|
|
|
|
Rect bottomLine = new Rect(initRect.x - 2f, initRect.y + toolbarHeight, initRect.width, 1f);
|
|
EditorGUI.DrawRect(bottomLine, new Color(0.4f, 0.4f, 0.5f, 1f));
|
|
|
|
string[][] subTexts = new string[rowCount][];
|
|
int offset = 0;
|
|
for (int i = 0; i < rowCount; i++)
|
|
{
|
|
if (i == rowCount - 1)
|
|
{
|
|
subTexts[i] = new string[lastRowButtons];
|
|
for (int j = 0; j < lastRowButtons; j++)
|
|
{
|
|
subTexts[i][j] = texts[offset++];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
subTexts[i] = new string[maxButtonsPerRow];
|
|
for (int j = 0; j < maxButtonsPerRow; j++)
|
|
{
|
|
subTexts[i][j] = texts[offset++];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int counter = 0;
|
|
for (int x = 0; x < rowCount; x++)
|
|
{
|
|
float buttonWidth = fillWidth
|
|
? x == rowCount - 1 ? rowWidth / lastRowButtons :
|
|
rowWidth / maxButtonsPerRow
|
|
: targetButtonWidth;
|
|
for (int y = 0; y < subTexts[x].Length; y++)
|
|
{
|
|
GUIStyle buttonStyle = new GUIStyle(EditorStyles.miniButtonMid);
|
|
buttonStyle.fixedHeight = buttonHeight;
|
|
|
|
Color initColor = GUI.color;
|
|
|
|
Rect buttonRect = new Rect(initRect.x + y * buttonWidth, initRect.y, buttonWidth,
|
|
rowHeight + 1);
|
|
|
|
if (tabIndex == counter)
|
|
{
|
|
GUI.color = new Color(1f, 1f, 1f, 1f);
|
|
}
|
|
else
|
|
{
|
|
GUI.color = new Color(0.9f, 0.9f, 0.9f, 1f);
|
|
}
|
|
|
|
if (GUI.Button(buttonRect, subTexts[x][y], buttonStyle))
|
|
{
|
|
tabIndex = counter;
|
|
}
|
|
|
|
if (tabIndex == counter)
|
|
{
|
|
Rect highlightRect = new Rect(buttonRect.x - 2f, buttonRect.y + buttonRect.height - 2,
|
|
buttonRect.width,
|
|
2);
|
|
EditorGUI.DrawRect(highlightRect, NUISettings.lightBlueColor);
|
|
}
|
|
|
|
GUI.color = initColor;
|
|
counter++;
|
|
}
|
|
|
|
initRect.y += rowHeight;
|
|
}
|
|
|
|
SetTabIndex(name, tabIndex);
|
|
EditorCache.SetHeightCacheValue(GenerateKey() + name, toolbarHeight);
|
|
}
|
|
else
|
|
{
|
|
EditorCache.GetHeightCacheValue(GenerateKey() + name, ref toolbarHeight);
|
|
}
|
|
|
|
AdvancePosition(toolbarHeight + 2);
|
|
return tabIndex;
|
|
}
|
|
|
|
|
|
public void IncreaseIndent()
|
|
{
|
|
positionRect = new Rect(positionRect.x + 6, positionRect.y, positionRect.width - 6, positionRect.height);
|
|
}
|
|
|
|
|
|
public void Indent(int indent, float step = 10f)
|
|
{
|
|
positionRect = new Rect(positionRect.x + indent * step, positionRect.y, positionRect.width - indent * step,
|
|
positionRect.height);
|
|
}
|
|
|
|
|
|
public void Info(string text, MessageType messageType = MessageType.Info)
|
|
{
|
|
GUIStyle style = new GUIStyle(GUI.skin.box);
|
|
style.alignment = TextAnchor.MiddleCenter;
|
|
style.wordWrap = true;
|
|
|
|
float height = 0;
|
|
if (positionRect.width > 20f)
|
|
{
|
|
float width = positionRect.width;
|
|
GUIContent content = new GUIContent(text);
|
|
height = style.CalcHeight(content, positionRect.width);
|
|
style.fixedHeight = height;
|
|
Rect infoRect = new Rect(positionRect.x, positionRect.y, positionRect.width, height);
|
|
EditorGUI.HelpBox(infoRect, text, messageType);
|
|
|
|
EditorCache.SetHeightCacheValue(GenerateKey() + text.GetHashCode(), height); // not the most optimal
|
|
}
|
|
else
|
|
{
|
|
EditorCache.GetHeightCacheValue(GenerateKey() + text.GetHashCode(), ref height);
|
|
}
|
|
|
|
AdvancePosition(height + NUISettings.fieldSpacing);
|
|
}
|
|
|
|
|
|
public void Label(string label, bool bold = false, bool active = true)
|
|
{
|
|
bool wasActive = GUI.enabled;
|
|
EditorGUI.BeginDisabledGroup(!active);
|
|
GUIStyle style = bold ? EditorStyles.boldLabel : EditorStyles.label;
|
|
EditorGUI.LabelField(new Rect(positionRect.x, positionRect.y, positionRect.width, NUISettings.fieldHeight),
|
|
new GUIContent(label), style);
|
|
if (wasActive)
|
|
{
|
|
EditorGUI.EndDisabledGroup();
|
|
}
|
|
|
|
AdvancePosition();
|
|
}
|
|
|
|
|
|
public void Property(string propertyName, bool drawChildren = true, bool expanded = true)
|
|
{
|
|
Property(FindProperty(propertyName), drawChildren, true);
|
|
}
|
|
|
|
|
|
public void Property(SerializedProperty p, bool includeChildren = true, bool expanded = true,
|
|
bool disabled = false)
|
|
{
|
|
if (p == null)
|
|
{
|
|
Debug.LogWarning("Property could not be found.");
|
|
return;
|
|
}
|
|
|
|
bool wasEnabled = GUI.enabled;
|
|
EditorGUI.BeginDisabledGroup(disabled);
|
|
|
|
p.isExpanded = true;
|
|
EditorGUI.PropertyField(positionRect, p, includeChildren);
|
|
|
|
AdvancePosition(EditorGUI.GetPropertyHeight(p) + NUISettings.fieldSpacing);
|
|
|
|
if (wasEnabled)
|
|
{
|
|
EditorGUI.EndDisabledGroup();
|
|
}
|
|
|
|
UpdateCachedKey();
|
|
}
|
|
|
|
|
|
public void ReorderableList(string propertyName, string label = null, bool draggable = true,
|
|
bool showAddRemoveButtons = true,
|
|
Type baseType = null, float elementSpacing = 0)
|
|
{
|
|
SerializedProperty listProperty = FindProperty(propertyName);
|
|
if (listProperty == null)
|
|
{
|
|
Debug.LogError("Property or SerializedObject is null.");
|
|
return;
|
|
}
|
|
|
|
ReorderableList reorderableList = null;
|
|
EditorCache.GetReorderableListCacheValue(GenerateKey(listProperty), ref reorderableList);
|
|
|
|
// A fix for Unity 2021.1 bug that causes issues with serializedProperty serializedObject becoming disposed
|
|
// and crashing the editor if assigned. Null check does not work in this case.
|
|
try
|
|
{
|
|
bool t = reorderableList.serializedProperty.name == null;
|
|
}
|
|
catch
|
|
{
|
|
reorderableList = new ReorderableList(listProperty.serializedObject, listProperty, draggable,
|
|
true, true, true);
|
|
}
|
|
|
|
if (reorderableList == null) return;
|
|
|
|
reorderableList.serializedProperty = listProperty;
|
|
reorderableList.displayAdd = showAddRemoveButtons;
|
|
reorderableList.displayRemove = showAddRemoveButtons;
|
|
|
|
if (reorderableList.serializedProperty == null) return;
|
|
|
|
string headerLabel = string.IsNullOrEmpty(label) ? listProperty.displayName : label;
|
|
reorderableList.drawHeaderCallback = rect => { EditorGUI.LabelField(rect, new GUIContent(headerLabel)); };
|
|
|
|
reorderableList.drawElementCallback = (rect, index, active, focused) =>
|
|
{
|
|
if (index < 0 || index > reorderableList.serializedProperty.arraySize - 1) return;
|
|
SerializedProperty p = listProperty.GetArrayElementAtIndex(index);
|
|
if (p == null) return;
|
|
EditorGUI.PropertyField(rect, p, true);
|
|
};
|
|
|
|
reorderableList.elementHeightCallback = index =>
|
|
{
|
|
if (index < 0 || index > reorderableList.serializedProperty.arraySize - 1) return 0;
|
|
SerializedProperty p =
|
|
listProperty.GetArrayElementAtIndex(index);
|
|
if (p == null) return 0;
|
|
float height = EditorGUI.GetPropertyHeight(p, true);
|
|
return height + elementSpacing + 1;
|
|
};
|
|
|
|
float listHeight = reorderableList.GetHeight() + 1;
|
|
Rect listRect = new Rect(positionRect.x, positionRect.y + 3f, positionRect.width, listHeight);
|
|
reorderableList.DoList(listRect);
|
|
|
|
AdvancePosition(listHeight + NUISettings.fieldSpacing);
|
|
|
|
EditorCache.SetReorderableListCacheValue(GenerateKey(listProperty), reorderableList);
|
|
}
|
|
|
|
|
|
public void SetHeight(float height)
|
|
{
|
|
SetHeight(_cachedKey, height);
|
|
}
|
|
|
|
|
|
public void SetHeight(string key, float height)
|
|
{
|
|
EditorCache.SetHeightCacheValue(key, height);
|
|
}
|
|
|
|
|
|
public void Space(float spaceSize = 5f)
|
|
{
|
|
AdvancePosition(spaceSize);
|
|
}
|
|
|
|
|
|
public void SplitRectVertically(Rect inRect, float splitPoint, out Rect rectA, out Rect rectB,
|
|
float centerMargin = 4f)
|
|
{
|
|
float rectAWidth = inRect.width * splitPoint;
|
|
rectA = new Rect(inRect.x, inRect.y, rectAWidth, inRect.height);
|
|
rectB = new Rect(inRect.x + rectAWidth + centerMargin, inRect.y, inRect.width - rectAWidth, inRect.height);
|
|
}
|
|
|
|
|
|
public void Title(string label)
|
|
{
|
|
GUIStyle style = new GUIStyle(EditorStyles.label);
|
|
style.fontStyle = FontStyle.Bold;
|
|
style.normal.textColor = EditorGUIUtility.isProSkin ? Color.white : Color.black;
|
|
|
|
EditorGUI.DrawRect(new Rect(new Vector2(positionRect.position.x, positionRect.position.y + 2),
|
|
new Vector2(positionRect.size.x, positionRect.size.y - 4f)),
|
|
EditorGUIUtility.isProSkin
|
|
? new Color(0.21f, 0.21f, 0.21f)
|
|
: NUISettings.lightGreyColor);
|
|
|
|
#if UNITY_2019_3_OR_NEWER
|
|
EditorGUI.LabelField(positionRect, new GUIContent(" " + label), style);
|
|
#else
|
|
EditorGUI.LabelField(new Rect(positionRect.x, positionRect.y + 3f, positionRect.width, positionRect.height),
|
|
new GUIContent(" " + label), style);
|
|
#endif
|
|
|
|
AdvancePosition();
|
|
}
|
|
|
|
|
|
private string AddSpacesToSentence(string text, bool preserveAcronyms)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(text))
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
StringBuilder newText = new StringBuilder(text.Length * 2);
|
|
newText.Append(text[0]);
|
|
for (int i = 1; i < text.Length; i++)
|
|
{
|
|
if (char.IsUpper(text[i]))
|
|
{
|
|
if (text[i - 1] != ' ' && !char.IsUpper(text[i - 1]) ||
|
|
preserveAcronyms && char.IsUpper(text[i - 1]) &&
|
|
i < text.Length - 1 && !char.IsUpper(text[i + 1]))
|
|
{
|
|
newText.Append(' ');
|
|
}
|
|
}
|
|
|
|
newText.Append(text[i]);
|
|
}
|
|
|
|
return newText.ToString();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|