322 lines
12 KiB
C#
322 lines
12 KiB
C#
|
using System;
|
|||
|
using UnityEngine;
|
|||
|
using UnityEditor;
|
|||
|
|
|||
|
|
|||
|
namespace TMPro.EditorUtilities
|
|||
|
{
|
|||
|
|
|||
|
[CustomPropertyDrawer(typeof(TMP_Style))]
|
|||
|
public class StyleDrawer : PropertyDrawer
|
|||
|
{
|
|||
|
public static readonly float height = 95f;
|
|||
|
|
|||
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
|||
|
{
|
|||
|
return height;
|
|||
|
}
|
|||
|
|
|||
|
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
|||
|
{
|
|||
|
SerializedProperty nameProperty = property.FindPropertyRelative("m_Name");
|
|||
|
SerializedProperty hashCodeProperty = property.FindPropertyRelative("m_HashCode");
|
|||
|
SerializedProperty openingDefinitionProperty = property.FindPropertyRelative("m_OpeningDefinition");
|
|||
|
SerializedProperty closingDefinitionProperty = property.FindPropertyRelative("m_ClosingDefinition");
|
|||
|
SerializedProperty openingDefinitionArray = property.FindPropertyRelative("m_OpeningTagArray");
|
|||
|
SerializedProperty closingDefinitionArray = property.FindPropertyRelative("m_ClosingTagArray");
|
|||
|
|
|||
|
|
|||
|
EditorGUIUtility.labelWidth = 86;
|
|||
|
position.height = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
|
|||
|
float labelHeight = position.height + 2f;
|
|||
|
|
|||
|
EditorGUI.BeginChangeCheck();
|
|||
|
Rect rect0 = new Rect(position.x, position.y, (position.width) / 2 + 5, position.height);
|
|||
|
EditorGUI.PropertyField(rect0, nameProperty);
|
|||
|
if (EditorGUI.EndChangeCheck())
|
|||
|
{
|
|||
|
// Recompute HashCode if name has changed.
|
|||
|
hashCodeProperty.intValue = TMP_TextUtilities.GetSimpleHashCode(nameProperty.stringValue);
|
|||
|
|
|||
|
property.serializedObject.ApplyModifiedProperties();
|
|||
|
|
|||
|
// Dictionary needs to be updated since HashCode has changed.
|
|||
|
TMP_StyleSheet styleSheet = property.serializedObject.targetObject as TMP_StyleSheet;
|
|||
|
styleSheet.RefreshStyles();
|
|||
|
}
|
|||
|
|
|||
|
// HashCode
|
|||
|
Rect rect1 = new Rect(rect0.x + rect0.width + 5, position.y, 65, position.height);
|
|||
|
GUI.Label(rect1, "HashCode");
|
|||
|
GUI.enabled = false;
|
|||
|
rect1.x += 65;
|
|||
|
rect1.width = position.width / 2 - 75;
|
|||
|
EditorGUI.PropertyField(rect1, hashCodeProperty, GUIContent.none);
|
|||
|
|
|||
|
GUI.enabled = true;
|
|||
|
|
|||
|
// Text Tags
|
|||
|
EditorGUI.BeginChangeCheck();
|
|||
|
|
|||
|
// Opening Tags
|
|||
|
position.y += labelHeight;
|
|||
|
GUI.Label(position, "Opening Tags");
|
|||
|
Rect textRect1 = new Rect(110, position.y, position.width - 86, 35);
|
|||
|
openingDefinitionProperty.stringValue = EditorGUI.TextArea(textRect1, openingDefinitionProperty.stringValue);
|
|||
|
if (EditorGUI.EndChangeCheck())
|
|||
|
{
|
|||
|
// If any properties have changed, we need to update the Opening and Closing Arrays.
|
|||
|
int size = openingDefinitionProperty.stringValue.Length;
|
|||
|
|
|||
|
// Adjust array size to match new string length.
|
|||
|
if (openingDefinitionArray.arraySize != size) openingDefinitionArray.arraySize = size;
|
|||
|
|
|||
|
for (int i = 0; i < size; i++)
|
|||
|
{
|
|||
|
SerializedProperty element = openingDefinitionArray.GetArrayElementAtIndex(i);
|
|||
|
element.intValue = openingDefinitionProperty.stringValue[i];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
EditorGUI.BeginChangeCheck();
|
|||
|
|
|||
|
// Closing Tags
|
|||
|
position.y += 38;
|
|||
|
GUI.Label(position, "Closing Tags");
|
|||
|
Rect textRect2 = new Rect(110, position.y, position.width - 86, 35);
|
|||
|
closingDefinitionProperty.stringValue = EditorGUI.TextArea(textRect2, closingDefinitionProperty.stringValue);
|
|||
|
|
|||
|
if (EditorGUI.EndChangeCheck())
|
|||
|
{
|
|||
|
// If any properties have changed, we need to update the Opening and Closing Arrays.
|
|||
|
int size = closingDefinitionProperty.stringValue.Length;
|
|||
|
|
|||
|
// Adjust array size to match new string length.
|
|||
|
if (closingDefinitionArray.arraySize != size) closingDefinitionArray.arraySize = size;
|
|||
|
|
|||
|
for (int i = 0; i < size; i++)
|
|||
|
{
|
|||
|
SerializedProperty element = closingDefinitionArray.GetArrayElementAtIndex(i);
|
|||
|
element.intValue = closingDefinitionProperty.stringValue[i];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
[CustomEditor(typeof(TMP_StyleSheet)), CanEditMultipleObjects]
|
|||
|
public class TMP_StyleEditor : Editor
|
|||
|
{
|
|||
|
|
|||
|
TMP_StyleSheet m_StyleSheet;
|
|||
|
SerializedProperty m_StyleListProp;
|
|||
|
|
|||
|
int m_SelectedElement = -1;
|
|||
|
int m_Page;
|
|||
|
|
|||
|
bool m_IsStyleSheetDirty;
|
|||
|
|
|||
|
|
|||
|
void OnEnable()
|
|||
|
{
|
|||
|
m_StyleSheet = target as TMP_StyleSheet;
|
|||
|
m_StyleListProp = serializedObject.FindProperty("m_StyleList");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public override void OnInspectorGUI()
|
|||
|
{
|
|||
|
Event currentEvent = Event.current;
|
|||
|
|
|||
|
serializedObject.Update();
|
|||
|
|
|||
|
m_IsStyleSheetDirty = false;
|
|||
|
int elementCount = m_StyleListProp.arraySize;
|
|||
|
int itemsPerPage = (Screen.height - 100) / 110;
|
|||
|
|
|||
|
if (elementCount > 0)
|
|||
|
{
|
|||
|
// Display each Style entry using the StyleDrawer PropertyDrawer.
|
|||
|
for (int i = itemsPerPage * m_Page; i < elementCount && i < itemsPerPage * (m_Page + 1); i++)
|
|||
|
{
|
|||
|
// Define the start of the selection region of the element.
|
|||
|
Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
|
|||
|
|
|||
|
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
|||
|
|
|||
|
SerializedProperty styleProperty = m_StyleListProp.GetArrayElementAtIndex(i);
|
|||
|
EditorGUI.BeginChangeCheck();
|
|||
|
EditorGUILayout.PropertyField(styleProperty);
|
|||
|
EditorGUILayout.EndVertical();
|
|||
|
if (EditorGUI.EndChangeCheck())
|
|||
|
{
|
|||
|
//
|
|||
|
}
|
|||
|
|
|||
|
// Define the end of the selection region of the element.
|
|||
|
Rect elementEndRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
|
|||
|
|
|||
|
// Check for Item selection
|
|||
|
Rect selectionArea = new Rect(elementStartRegion.x, elementStartRegion.y, elementEndRegion.width, elementEndRegion.y - elementStartRegion.y);
|
|||
|
if (DoSelectionCheck(selectionArea))
|
|||
|
{
|
|||
|
if (m_SelectedElement == i)
|
|||
|
{
|
|||
|
m_SelectedElement = -1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
m_SelectedElement = i;
|
|||
|
GUIUtility.keyboardControl = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Handle Selection Highlighting
|
|||
|
if (m_SelectedElement == i)
|
|||
|
TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// STYLE LIST MANAGEMENT
|
|||
|
Rect rect = EditorGUILayout.GetControlRect(false, 20);
|
|||
|
float totalWidth = rect.width;
|
|||
|
rect.width = totalWidth * 0.175f;
|
|||
|
|
|||
|
// Move Style up.
|
|||
|
bool guiEnabled = GUI.enabled;
|
|||
|
if (m_SelectedElement == -1 || m_SelectedElement == 0) { GUI.enabled = false; }
|
|||
|
if (GUI.Button(rect, "Up"))
|
|||
|
{
|
|||
|
SwapStyleElements(m_SelectedElement, m_SelectedElement - 1);
|
|||
|
}
|
|||
|
GUI.enabled = guiEnabled;
|
|||
|
|
|||
|
// Move Style down.
|
|||
|
rect.x += rect.width;
|
|||
|
if (m_SelectedElement == elementCount - 1) { GUI.enabled = false; }
|
|||
|
if (GUI.Button(rect, "Down"))
|
|||
|
{
|
|||
|
SwapStyleElements(m_SelectedElement, m_SelectedElement + 1);
|
|||
|
}
|
|||
|
GUI.enabled = guiEnabled;
|
|||
|
|
|||
|
// Add Style
|
|||
|
rect.x += rect.width + totalWidth * 0.3f;
|
|||
|
if (GUI.Button(rect, "+"))
|
|||
|
{
|
|||
|
int index = m_SelectedElement == -1 ? elementCount : m_SelectedElement;
|
|||
|
|
|||
|
if (index > elementCount)
|
|||
|
index = elementCount;
|
|||
|
|
|||
|
// Copy selected element
|
|||
|
m_StyleListProp.InsertArrayElementAtIndex(index);
|
|||
|
|
|||
|
// Select newly inserted element
|
|||
|
m_SelectedElement = index + 1;
|
|||
|
|
|||
|
serializedObject.ApplyModifiedProperties();
|
|||
|
m_StyleSheet.RefreshStyles();
|
|||
|
}
|
|||
|
|
|||
|
// Delete style
|
|||
|
rect.x += rect.width;
|
|||
|
if (m_SelectedElement == -1 || m_SelectedElement >= elementCount) GUI.enabled = false;
|
|||
|
if (GUI.Button(rect, "-"))
|
|||
|
{
|
|||
|
int index = m_SelectedElement == -1 ? 0 : m_SelectedElement;
|
|||
|
|
|||
|
m_StyleListProp.DeleteArrayElementAtIndex(index);
|
|||
|
|
|||
|
m_SelectedElement = -1;
|
|||
|
serializedObject.ApplyModifiedProperties();
|
|||
|
m_StyleSheet.RefreshStyles();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// Return if we can't display any items.
|
|||
|
if (itemsPerPage == 0) return;
|
|||
|
|
|||
|
// DISPLAY PAGE CONTROLS
|
|||
|
int shiftMultiplier = currentEvent.shift ? 10 : 1; // Page + Shift goes 10 page forward
|
|||
|
|
|||
|
Rect pagePos = EditorGUILayout.GetControlRect(false, 20);
|
|||
|
pagePos.width = totalWidth * 0.35f;
|
|||
|
|
|||
|
// Previous Page
|
|||
|
if (m_Page > 0) GUI.enabled = true;
|
|||
|
else GUI.enabled = false;
|
|||
|
|
|||
|
if (GUI.Button(pagePos, "Previous"))
|
|||
|
m_Page -= 1 * shiftMultiplier;
|
|||
|
|
|||
|
// PAGE COUNTER
|
|||
|
GUI.enabled = true;
|
|||
|
pagePos.x += pagePos.width;
|
|||
|
pagePos.width = totalWidth * 0.30f;
|
|||
|
int totalPages = (int)(elementCount / (float)itemsPerPage + 0.999f);
|
|||
|
GUI.Label(pagePos, "Page " + (m_Page + 1) + " / " + totalPages, TMP_UIStyleManager.centeredLabel);
|
|||
|
|
|||
|
// Next Page
|
|||
|
pagePos.x += pagePos.width;
|
|||
|
pagePos.width = totalWidth * 0.35f;
|
|||
|
if (itemsPerPage * (m_Page + 1) < elementCount) GUI.enabled = true;
|
|||
|
else GUI.enabled = false;
|
|||
|
|
|||
|
if (GUI.Button(pagePos, "Next"))
|
|||
|
m_Page += 1 * shiftMultiplier;
|
|||
|
|
|||
|
// Clamp page range
|
|||
|
m_Page = Mathf.Clamp(m_Page, 0, elementCount / itemsPerPage);
|
|||
|
|
|||
|
|
|||
|
if (serializedObject.ApplyModifiedProperties())
|
|||
|
{
|
|||
|
TMPro_EventManager.ON_TEXT_STYLE_PROPERTY_CHANGED(true);
|
|||
|
|
|||
|
if (m_IsStyleSheetDirty)
|
|||
|
{
|
|||
|
m_IsStyleSheetDirty = false;
|
|||
|
m_StyleSheet.RefreshStyles();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Clear selection if mouse event was not consumed.
|
|||
|
GUI.enabled = true;
|
|||
|
if (currentEvent.type == EventType.MouseDown && currentEvent.button == 0)
|
|||
|
m_SelectedElement = -1;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// Check if any of the Style elements were clicked on.
|
|||
|
static bool DoSelectionCheck(Rect selectionArea)
|
|||
|
{
|
|||
|
Event currentEvent = Event.current;
|
|||
|
|
|||
|
switch (currentEvent.type)
|
|||
|
{
|
|||
|
case EventType.MouseDown:
|
|||
|
if (selectionArea.Contains(currentEvent.mousePosition) && currentEvent.button == 0)
|
|||
|
{
|
|||
|
currentEvent.Use();
|
|||
|
return true;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
void SwapStyleElements(int selectedIndex, int newIndex)
|
|||
|
{
|
|||
|
m_StyleListProp.MoveArrayElement(selectedIndex, newIndex);
|
|||
|
m_SelectedElement = newIndex;
|
|||
|
m_IsStyleSheetDirty = true;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|