initial project folder
This commit is contained in:
@ -0,0 +1,60 @@
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(TMP_Dropdown.OptionDataList), true)]
|
||||
class DropdownOptionListDrawer : PropertyDrawer
|
||||
{
|
||||
private ReorderableList m_ReorderableList;
|
||||
|
||||
private void Init(SerializedProperty property)
|
||||
{
|
||||
if (m_ReorderableList != null)
|
||||
return;
|
||||
|
||||
SerializedProperty array = property.FindPropertyRelative("m_Options");
|
||||
|
||||
m_ReorderableList = new ReorderableList(property.serializedObject, array);
|
||||
m_ReorderableList.drawElementCallback = DrawOptionData;
|
||||
m_ReorderableList.drawHeaderCallback = DrawHeader;
|
||||
m_ReorderableList.elementHeight += 16;
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
Init(property);
|
||||
|
||||
m_ReorderableList.DoList(position);
|
||||
}
|
||||
|
||||
private void DrawHeader(Rect rect)
|
||||
{
|
||||
GUI.Label(rect, "Options");
|
||||
}
|
||||
|
||||
private void DrawOptionData(Rect rect, int index, bool isActive, bool isFocused)
|
||||
{
|
||||
SerializedProperty itemData = m_ReorderableList.serializedProperty.GetArrayElementAtIndex(index);
|
||||
SerializedProperty itemText = itemData.FindPropertyRelative("m_Text");
|
||||
SerializedProperty itemImage = itemData.FindPropertyRelative("m_Image");
|
||||
|
||||
RectOffset offset = new RectOffset(0, 0, -1, -3);
|
||||
rect = offset.Add(rect);
|
||||
rect.height = EditorGUIUtility.singleLineHeight;
|
||||
|
||||
EditorGUI.PropertyField(rect, itemText, GUIContent.none);
|
||||
rect.y += EditorGUIUtility.singleLineHeight;
|
||||
EditorGUI.PropertyField(rect, itemImage, GUIContent.none);
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
Init(property);
|
||||
|
||||
return m_ReorderableList.GetHeight();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9545c9eb3bf94265810463794fec8334
|
||||
timeCreated: 1464818008
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
[CustomPropertyDrawer(typeof(TMP_Glyph))]
|
||||
public class GlyphInfoDrawer : PropertyDrawer
|
||||
{
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
SerializedProperty prop_id = property.FindPropertyRelative("id");
|
||||
SerializedProperty prop_x = property.FindPropertyRelative("x");
|
||||
SerializedProperty prop_y = property.FindPropertyRelative("y");
|
||||
SerializedProperty prop_width = property.FindPropertyRelative("width");
|
||||
SerializedProperty prop_height = property.FindPropertyRelative("height");
|
||||
SerializedProperty prop_xOffset = property.FindPropertyRelative("xOffset");
|
||||
SerializedProperty prop_yOffset = property.FindPropertyRelative("yOffset");
|
||||
SerializedProperty prop_xAdvance = property.FindPropertyRelative("xAdvance");
|
||||
SerializedProperty prop_scale = property.FindPropertyRelative("scale");
|
||||
|
||||
|
||||
// We get Rect since a valid position may not be provided by the caller.
|
||||
Rect rect = GUILayoutUtility.GetRect(position.width, 48);
|
||||
rect.y -= 15;
|
||||
|
||||
//GUI.enabled = false;
|
||||
EditorGUIUtility.labelWidth = 40f;
|
||||
EditorGUIUtility.fieldWidth = 45f;
|
||||
|
||||
bool prevGuiState = GUI.enabled;
|
||||
GUI.enabled = true;
|
||||
EditorGUI.LabelField(new Rect(rect.x + 5f, rect.y, 80f, 18), new GUIContent("Ascii: <color=#FFFF80>" + prop_id.intValue + "</color>"), TMP_UIStyleManager.label);
|
||||
EditorGUI.LabelField(new Rect(rect.x + 90f, rect.y, 80f, 18), new GUIContent("Hex: <color=#FFFF80>" + prop_id.intValue.ToString("X") + "</color>"), TMP_UIStyleManager.label);
|
||||
EditorGUI.LabelField(new Rect(rect.x + 170f, rect.y, 80, 18), "Char: [ <color=#FFFF80>" + (char)prop_id.intValue + "</color> ]", TMP_UIStyleManager.label);
|
||||
GUI.enabled = prevGuiState;
|
||||
|
||||
EditorGUIUtility.labelWidth = 35f;
|
||||
EditorGUIUtility.fieldWidth = 10f;
|
||||
|
||||
float width = (rect.width - 5f) / 4;
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 5f + width * 0, rect.y + 22, width - 5f, 18), prop_x, new GUIContent("X:"));
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 5f + width * 1, rect.y + 22, width - 5f, 18), prop_y, new GUIContent("Y:"));
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 5f + width * 2, rect.y + 22, width - 5f, 18), prop_width, new GUIContent("W:"));
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 5f + width * 3, rect.y + 22, width - 5f, 18), prop_height, new GUIContent("H:"));
|
||||
|
||||
//GUI.enabled = true;
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 5f + width * 0, rect.y + 44, width - 5f, 18), prop_xOffset, new GUIContent("OX:"));
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 5f + width * 1, rect.y + 44, width - 5f, 18), prop_yOffset, new GUIContent("OY:"));
|
||||
//GUI.enabled = true;
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 5f + width * 2, rect.y + 44, width - 5f, 18), prop_xAdvance, new GUIContent("ADV:"));
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 5f + width * 3, rect.y + 44, width - 5f, 18), prop_scale, new GUIContent("SF:"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 900f1a451c764dc3bdcc0de815a15935
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,53 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.TextCore;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
[CustomPropertyDrawer(typeof(GlyphMetrics))]
|
||||
public class GlyphMetricsPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
SerializedProperty prop_Width = property.FindPropertyRelative("m_Width");
|
||||
SerializedProperty prop_Height = property.FindPropertyRelative("m_Height");
|
||||
SerializedProperty prop_HoriBearingX = property.FindPropertyRelative("m_HorizontalBearingX");
|
||||
SerializedProperty prop_HoriBearingY = property.FindPropertyRelative("m_HorizontalBearingY");
|
||||
SerializedProperty prop_HoriAdvance = property.FindPropertyRelative("m_HorizontalAdvance");
|
||||
|
||||
// We get Rect since a valid position may not be provided by the caller.
|
||||
Rect rect = new Rect(position.x, position.y, position.width, 49);
|
||||
|
||||
EditorGUI.LabelField(rect, new GUIContent("Glyph Metrics"));
|
||||
|
||||
EditorGUIUtility.labelWidth = 30f;
|
||||
EditorGUIUtility.fieldWidth = 10f;
|
||||
|
||||
//GUI.enabled = false;
|
||||
float width = (rect.width - 75f) / 2;
|
||||
EditorGUI.PropertyField(new Rect(rect.x + width * 0, rect.y + 20, width - 5f, 18), prop_Width, new GUIContent("W:"));
|
||||
EditorGUI.PropertyField(new Rect(rect.x + width * 1, rect.y + 20, width - 5f, 18), prop_Height, new GUIContent("H:"));
|
||||
|
||||
//GUI.enabled = true;
|
||||
|
||||
width = (rect.width - 75f) / 3;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.PropertyField(new Rect(rect.x + width * 0, rect.y + 40, width - 5f, 18), prop_HoriBearingX, new GUIContent("BX:"));
|
||||
EditorGUI.PropertyField(new Rect(rect.x + width * 1, rect.y + 40, width - 5f, 18), prop_HoriBearingY, new GUIContent("BY:"));
|
||||
EditorGUI.PropertyField(new Rect(rect.x + width * 2, rect.y + 40, width - 5f, 18), prop_HoriAdvance, new GUIContent("AD:"));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return 65f;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3882522a08b6f5459b4dea6f8791278
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,44 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.TextCore;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
[CustomPropertyDrawer(typeof(GlyphRect))]
|
||||
public class GlyphRectPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
//EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
SerializedProperty prop_X = property.FindPropertyRelative("m_X");
|
||||
SerializedProperty prop_Y = property.FindPropertyRelative("m_Y");
|
||||
SerializedProperty prop_Width = property.FindPropertyRelative("m_Width");
|
||||
SerializedProperty prop_Height = property.FindPropertyRelative("m_Height");
|
||||
|
||||
// We get Rect since a valid position may not be provided by the caller.
|
||||
Rect rect = new Rect(position.x, position.y, position.width, 49);
|
||||
EditorGUI.LabelField(rect, new GUIContent("Glyph Rect"));
|
||||
|
||||
EditorGUIUtility.labelWidth = 30f;
|
||||
EditorGUIUtility.fieldWidth = 10f;
|
||||
|
||||
//GUI.enabled = false;
|
||||
float width = (rect.width - 75f) / 4;
|
||||
EditorGUI.PropertyField(new Rect(rect.x + width * 0, rect.y + 20, width - 5f, 18), prop_X, new GUIContent("X:"));
|
||||
EditorGUI.PropertyField(new Rect(rect.x + width * 1, rect.y + 20, width - 5f, 18), prop_Y, new GUIContent("Y:"));
|
||||
EditorGUI.PropertyField(new Rect(rect.x + width * 2, rect.y + 20, width - 5f, 18), prop_Width, new GUIContent("W:"));
|
||||
EditorGUI.PropertyField(new Rect(rect.x + width * 3, rect.y + 20, width - 5f, 18), prop_Height, new GUIContent("H:"));
|
||||
|
||||
//EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return 45f;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8bc2b083b068f3546a9509c805e0541c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91950f78729ab144aa36e94690b28fad
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,534 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
/// <summary>Base class for TextMesh Pro shader GUIs.</summary>
|
||||
public abstract class TMP_BaseShaderGUI : ShaderGUI
|
||||
{
|
||||
/// <summary>Representation of a #pragma shader_feature.</summary>
|
||||
/// <description>It is assumed that the first feature option is for no keyword (underscores).</description>
|
||||
protected class ShaderFeature
|
||||
{
|
||||
public string undoLabel;
|
||||
|
||||
public GUIContent label;
|
||||
|
||||
/// <summary>The keyword labels, for display. Include the no-keyword as the first option.</summary>
|
||||
public GUIContent[] keywordLabels;
|
||||
|
||||
/// <summary>The shader keywords. Exclude the no-keyword option.</summary>
|
||||
public string[] keywords;
|
||||
|
||||
int m_State;
|
||||
|
||||
public bool Active
|
||||
{
|
||||
get { return m_State >= 0; }
|
||||
}
|
||||
|
||||
public int State
|
||||
{
|
||||
get { return m_State; }
|
||||
}
|
||||
|
||||
public void ReadState(Material material)
|
||||
{
|
||||
for (int i = 0; i < keywords.Length; i++)
|
||||
{
|
||||
if (material.IsKeywordEnabled(keywords[i]))
|
||||
{
|
||||
m_State = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_State = -1;
|
||||
}
|
||||
|
||||
public void SetActive(bool active, Material material)
|
||||
{
|
||||
m_State = active ? 0 : -1;
|
||||
SetStateKeywords(material);
|
||||
}
|
||||
|
||||
public void DoPopup(MaterialEditor editor, Material material)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
int selection = EditorGUILayout.Popup(label, m_State + 1, keywordLabels);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
m_State = selection - 1;
|
||||
editor.RegisterPropertyChangeUndo(undoLabel);
|
||||
SetStateKeywords(material);
|
||||
}
|
||||
}
|
||||
|
||||
void SetStateKeywords(Material material)
|
||||
{
|
||||
for (int i = 0; i < keywords.Length; i++)
|
||||
{
|
||||
if (i == m_State)
|
||||
{
|
||||
material.EnableKeyword(keywords[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
material.DisableKeyword(keywords[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GUIContent s_TempLabel = new GUIContent();
|
||||
|
||||
protected static bool s_DebugExtended;
|
||||
|
||||
static int s_UndoRedoCount, s_LastSeenUndoRedoCount;
|
||||
|
||||
static float[][] s_TempFloats =
|
||||
{
|
||||
null, new float[1], new float[2], new float[3], new float[4]
|
||||
};
|
||||
|
||||
protected static GUIContent[] s_XywhVectorLabels =
|
||||
{
|
||||
new GUIContent("X"),
|
||||
new GUIContent("Y"),
|
||||
new GUIContent("W", "Width"),
|
||||
new GUIContent("H", "Height")
|
||||
};
|
||||
|
||||
protected static GUIContent[] s_LbrtVectorLabels =
|
||||
{
|
||||
new GUIContent("L", "Left"),
|
||||
new GUIContent("B", "Bottom"),
|
||||
new GUIContent("R", "Right"),
|
||||
new GUIContent("T", "Top")
|
||||
};
|
||||
|
||||
static TMP_BaseShaderGUI()
|
||||
{
|
||||
// Keep track of how many undo/redo events happened.
|
||||
Undo.undoRedoPerformed += () => s_UndoRedoCount += 1;
|
||||
}
|
||||
|
||||
bool m_IsNewGUI = true;
|
||||
|
||||
float m_DragAndDropMinY;
|
||||
|
||||
protected MaterialEditor m_Editor;
|
||||
|
||||
protected Material m_Material;
|
||||
|
||||
protected MaterialProperty[] m_Properties;
|
||||
|
||||
void PrepareGUI()
|
||||
{
|
||||
m_IsNewGUI = false;
|
||||
ShaderUtilities.GetShaderPropertyIDs();
|
||||
|
||||
// New GUI just got constructed. This happens in response to a selection,
|
||||
// but also after undo/redo events.
|
||||
if (s_LastSeenUndoRedoCount != s_UndoRedoCount)
|
||||
{
|
||||
// There's been at least one undo/redo since the last time this GUI got constructed.
|
||||
// Maybe the undo/redo was for this material? Assume that is was.
|
||||
TMPro_EventManager.ON_MATERIAL_PROPERTY_CHANGED(true, m_Material as Material);
|
||||
}
|
||||
|
||||
s_LastSeenUndoRedoCount = s_UndoRedoCount;
|
||||
}
|
||||
|
||||
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
|
||||
{
|
||||
m_Editor = materialEditor;
|
||||
m_Material = materialEditor.target as Material;
|
||||
this.m_Properties = properties;
|
||||
|
||||
if (m_IsNewGUI)
|
||||
{
|
||||
PrepareGUI();
|
||||
}
|
||||
|
||||
DoDragAndDropBegin();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
DoGUI();
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
TMPro_EventManager.ON_MATERIAL_PROPERTY_CHANGED(true, m_Material);
|
||||
}
|
||||
|
||||
DoDragAndDropEnd();
|
||||
}
|
||||
|
||||
/// <summary>Override this method to create the specific shader GUI.</summary>
|
||||
protected abstract void DoGUI();
|
||||
|
||||
static string[] s_PanelStateLabel = new string[] { "\t- <i>Click to collapse</i> -", "\t- <i>Click to expand</i> -" };
|
||||
|
||||
protected bool BeginPanel(string panel, bool expanded)
|
||||
{
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
|
||||
Rect r = EditorGUI.IndentedRect(GUILayoutUtility.GetRect(20, 18));
|
||||
r.x += 20;
|
||||
r.width += 6;
|
||||
|
||||
bool enabled = GUI.enabled;
|
||||
GUI.enabled = true;
|
||||
expanded = TMP_EditorUtility.EditorToggle(r, expanded, new GUIContent(panel), TMP_UIStyleManager.panelTitle);
|
||||
r.width -= 30;
|
||||
EditorGUI.LabelField(r, new GUIContent(expanded ? s_PanelStateLabel[0] : s_PanelStateLabel[1]), TMP_UIStyleManager.rightLabel);
|
||||
GUI.enabled = enabled;
|
||||
|
||||
EditorGUI.indentLevel += 1;
|
||||
EditorGUI.BeginDisabledGroup(false);
|
||||
|
||||
return expanded;
|
||||
}
|
||||
|
||||
protected bool BeginPanel(string panel, ShaderFeature feature, bool expanded, bool readState = true)
|
||||
{
|
||||
if (readState)
|
||||
{
|
||||
feature.ReadState(m_Material);
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.BeginHorizontal();
|
||||
|
||||
Rect r = EditorGUI.IndentedRect(GUILayoutUtility.GetRect(20, 20, GUILayout.Width(20f)));
|
||||
bool active = EditorGUI.Toggle(r, feature.Active);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
m_Editor.RegisterPropertyChangeUndo(feature.undoLabel);
|
||||
feature.SetActive(active, m_Material);
|
||||
}
|
||||
|
||||
r = EditorGUI.IndentedRect(GUILayoutUtility.GetRect(20, 18));
|
||||
r.width += 6;
|
||||
|
||||
bool enabled = GUI.enabled;
|
||||
GUI.enabled = true;
|
||||
expanded = TMP_EditorUtility.EditorToggle(r, expanded, new GUIContent(panel), TMP_UIStyleManager.panelTitle);
|
||||
r.width -= 10;
|
||||
EditorGUI.LabelField(r, new GUIContent(expanded ? s_PanelStateLabel[0] : s_PanelStateLabel[1]), TMP_UIStyleManager.rightLabel);
|
||||
GUI.enabled = enabled;
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
EditorGUI.indentLevel += 1;
|
||||
EditorGUI.BeginDisabledGroup(!active);
|
||||
|
||||
return expanded;
|
||||
}
|
||||
|
||||
public void EndPanel()
|
||||
{
|
||||
EditorGUI.EndDisabledGroup();
|
||||
EditorGUI.indentLevel -= 1;
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
MaterialProperty BeginProperty(string name)
|
||||
{
|
||||
MaterialProperty property = FindProperty(name, m_Properties);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.showMixedValue = property.hasMixedValue;
|
||||
m_Editor.BeginAnimatedCheck(Rect.zero, property);
|
||||
|
||||
return property;
|
||||
}
|
||||
|
||||
bool EndProperty()
|
||||
{
|
||||
m_Editor.EndAnimatedCheck();
|
||||
EditorGUI.showMixedValue = false;
|
||||
return EditorGUI.EndChangeCheck();
|
||||
}
|
||||
|
||||
protected void DoPopup(string name, string label, GUIContent[] options)
|
||||
{
|
||||
MaterialProperty property = BeginProperty(name);
|
||||
s_TempLabel.text = label;
|
||||
int index = EditorGUILayout.Popup(s_TempLabel, (int)property.floatValue, options);
|
||||
if (EndProperty())
|
||||
{
|
||||
property.floatValue = index;
|
||||
}
|
||||
}
|
||||
|
||||
protected void DoCubeMap(string name, string label)
|
||||
{
|
||||
DoTexture(name, label, typeof(Cubemap));
|
||||
}
|
||||
|
||||
protected void DoTexture2D(string name, string label, bool withTilingOffset = false, string[] speedNames = null)
|
||||
{
|
||||
DoTexture(name, label, typeof(Texture2D), withTilingOffset, speedNames);
|
||||
}
|
||||
|
||||
void DoTexture(string name, string label, System.Type type, bool withTilingOffset = false, string[] speedNames = null)
|
||||
{
|
||||
MaterialProperty property = BeginProperty(name);
|
||||
Rect rect = EditorGUILayout.GetControlRect(true, 60f);
|
||||
float totalWidth = rect.width;
|
||||
rect.width = EditorGUIUtility.labelWidth + 60f;
|
||||
s_TempLabel.text = label;
|
||||
Object tex = EditorGUI.ObjectField(rect, s_TempLabel, property.textureValue, type, false);
|
||||
|
||||
if (EndProperty())
|
||||
{
|
||||
property.textureValue = tex as Texture;
|
||||
}
|
||||
|
||||
rect.x += rect.width + 4f;
|
||||
rect.width = totalWidth - rect.width - 4f;
|
||||
rect.height = EditorGUIUtility.singleLineHeight;
|
||||
|
||||
if (withTilingOffset)
|
||||
{
|
||||
DoTilingOffset(rect, property);
|
||||
rect.y += (rect.height + 2f) * 2f;
|
||||
}
|
||||
|
||||
if (speedNames != null)
|
||||
{
|
||||
DoUVSpeed(rect, speedNames);
|
||||
}
|
||||
}
|
||||
|
||||
void DoTilingOffset(Rect rect, MaterialProperty property)
|
||||
{
|
||||
float labelWidth = EditorGUIUtility.labelWidth;
|
||||
int indentLevel = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
EditorGUIUtility.labelWidth = Mathf.Min(40f, rect.width * 0.20f);
|
||||
|
||||
Vector4 vector = property.textureScaleAndOffset;
|
||||
|
||||
bool changed = false;
|
||||
float[] values = s_TempFloats[2];
|
||||
|
||||
s_TempLabel.text = "Tiling";
|
||||
Rect vectorRect = EditorGUI.PrefixLabel(rect, s_TempLabel);
|
||||
values[0] = vector.x;
|
||||
values[1] = vector.y;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.MultiFloatField(vectorRect, s_XywhVectorLabels, values);
|
||||
if (EndProperty())
|
||||
{
|
||||
vector.x = values[0];
|
||||
vector.y = values[1];
|
||||
changed = true;
|
||||
}
|
||||
|
||||
rect.y += rect.height + 2f;
|
||||
s_TempLabel.text = "Offset";
|
||||
vectorRect = EditorGUI.PrefixLabel(rect, s_TempLabel);
|
||||
values[0] = vector.z;
|
||||
values[1] = vector.w;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.MultiFloatField(vectorRect, s_XywhVectorLabels, values);
|
||||
if (EndProperty())
|
||||
{
|
||||
vector.z = values[0];
|
||||
vector.w = values[1];
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
property.textureScaleAndOffset = vector;
|
||||
}
|
||||
|
||||
EditorGUIUtility.labelWidth = labelWidth;
|
||||
EditorGUI.indentLevel = indentLevel;
|
||||
}
|
||||
|
||||
protected void DoUVSpeed(Rect rect, string[] names)
|
||||
{
|
||||
float labelWidth = EditorGUIUtility.labelWidth;
|
||||
int indentLevel = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
EditorGUIUtility.labelWidth = Mathf.Min(40f, rect.width * 0.20f);
|
||||
|
||||
s_TempLabel.text = "Speed";
|
||||
rect = EditorGUI.PrefixLabel(rect, s_TempLabel);
|
||||
|
||||
EditorGUIUtility.labelWidth = 13f;
|
||||
rect.width = rect.width * 0.5f - 1f;
|
||||
DoFloat(rect, names[0], "X");
|
||||
rect.x += rect.width + 2f;
|
||||
DoFloat(rect, names[1], "Y");
|
||||
EditorGUIUtility.labelWidth = labelWidth;
|
||||
EditorGUI.indentLevel = indentLevel;
|
||||
}
|
||||
|
||||
protected void DoToggle(string name, string label)
|
||||
{
|
||||
MaterialProperty property = BeginProperty(name);
|
||||
s_TempLabel.text = label;
|
||||
bool value = EditorGUILayout.Toggle(s_TempLabel, property.floatValue == 1f);
|
||||
if (EndProperty())
|
||||
{
|
||||
property.floatValue = value ? 1f : 0f;
|
||||
}
|
||||
}
|
||||
|
||||
protected void DoFloat(string name, string label)
|
||||
{
|
||||
MaterialProperty property = BeginProperty(name);
|
||||
Rect rect = EditorGUILayout.GetControlRect();
|
||||
rect.width = EditorGUIUtility.labelWidth + 55f;
|
||||
s_TempLabel.text = label;
|
||||
float value = EditorGUI.FloatField(rect, s_TempLabel, property.floatValue);
|
||||
if (EndProperty())
|
||||
{
|
||||
property.floatValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected void DoColor(string name, string label)
|
||||
{
|
||||
MaterialProperty property = BeginProperty(name);
|
||||
s_TempLabel.text = label;
|
||||
Color value = EditorGUI.ColorField(EditorGUILayout.GetControlRect(), s_TempLabel, property.colorValue);
|
||||
if (EndProperty())
|
||||
{
|
||||
property.colorValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
void DoFloat(Rect rect, string name, string label)
|
||||
{
|
||||
MaterialProperty property = BeginProperty(name);
|
||||
s_TempLabel.text = label;
|
||||
float value = EditorGUI.FloatField(rect, s_TempLabel, property.floatValue);
|
||||
if (EndProperty())
|
||||
{
|
||||
property.floatValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected void DoSlider(string name, string label)
|
||||
{
|
||||
MaterialProperty property = BeginProperty(name);
|
||||
Vector2 range = property.rangeLimits;
|
||||
s_TempLabel.text = label;
|
||||
float value = EditorGUI.Slider(
|
||||
EditorGUILayout.GetControlRect(), s_TempLabel, property.floatValue, range.x, range.y
|
||||
);
|
||||
if (EndProperty())
|
||||
{
|
||||
property.floatValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected void DoVector3(string name, string label)
|
||||
{
|
||||
MaterialProperty property = BeginProperty(name);
|
||||
s_TempLabel.text = label;
|
||||
Vector4 value = EditorGUILayout.Vector3Field(s_TempLabel, property.vectorValue);
|
||||
if (EndProperty())
|
||||
{
|
||||
property.vectorValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected void DoVector(string name, string label, GUIContent[] subLabels)
|
||||
{
|
||||
MaterialProperty property = BeginProperty(name);
|
||||
Rect rect = EditorGUILayout.GetControlRect();
|
||||
s_TempLabel.text = label;
|
||||
rect = EditorGUI.PrefixLabel(rect, s_TempLabel);
|
||||
Vector4 vector = property.vectorValue;
|
||||
|
||||
float[] values = s_TempFloats[subLabels.Length];
|
||||
for (int i = 0; i < subLabels.Length; i++)
|
||||
{
|
||||
values[i] = vector[i];
|
||||
}
|
||||
|
||||
EditorGUI.MultiFloatField(rect, subLabels, values);
|
||||
if (EndProperty())
|
||||
{
|
||||
for (int i = 0; i < subLabels.Length; i++)
|
||||
{
|
||||
vector[i] = values[i];
|
||||
}
|
||||
|
||||
property.vectorValue = vector;
|
||||
}
|
||||
}
|
||||
|
||||
void DoDragAndDropBegin()
|
||||
{
|
||||
m_DragAndDropMinY = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true)).y;
|
||||
}
|
||||
|
||||
void DoDragAndDropEnd()
|
||||
{
|
||||
Rect rect = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
|
||||
Event evt = Event.current;
|
||||
if (evt.type == EventType.DragUpdated)
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
|
||||
evt.Use();
|
||||
}
|
||||
else if (
|
||||
evt.type == EventType.DragPerform &&
|
||||
Rect.MinMaxRect(rect.xMin, m_DragAndDropMinY, rect.xMax, rect.yMax).Contains(evt.mousePosition)
|
||||
)
|
||||
{
|
||||
DragAndDrop.AcceptDrag();
|
||||
evt.Use();
|
||||
Material droppedMaterial = DragAndDrop.objectReferences[0] as Material;
|
||||
if (droppedMaterial && droppedMaterial != m_Material)
|
||||
{
|
||||
PerformDrop(droppedMaterial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PerformDrop(Material droppedMaterial)
|
||||
{
|
||||
Texture droppedTex = droppedMaterial.GetTexture(ShaderUtilities.ID_MainTex);
|
||||
if (!droppedTex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Texture currentTex = m_Material.GetTexture(ShaderUtilities.ID_MainTex);
|
||||
TMP_FontAsset requiredFontAsset = null;
|
||||
if (droppedTex != currentTex)
|
||||
{
|
||||
requiredFontAsset = TMP_EditorUtility.FindMatchingFontAsset(droppedMaterial);
|
||||
if (!requiredFontAsset)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (GameObject o in Selection.gameObjects)
|
||||
{
|
||||
if (requiredFontAsset)
|
||||
{
|
||||
TMP_Text textComponent = o.GetComponent<TMP_Text>();
|
||||
if (textComponent)
|
||||
{
|
||||
Undo.RecordObject(textComponent, "Font Asset Change");
|
||||
textComponent.font = requiredFontAsset;
|
||||
}
|
||||
}
|
||||
|
||||
TMPro_EventManager.ON_DRAG_AND_DROP_MATERIAL_CHANGED(o, m_Material, droppedMaterial);
|
||||
EditorUtility.SetDirty(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 438efd46088d408d8a53f707fa68d976
|
||||
timeCreated: 1469844810
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,85 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
public class TMP_BitmapShaderGUI : TMP_BaseShaderGUI
|
||||
{
|
||||
static bool s_Face = true;
|
||||
|
||||
protected override void DoGUI()
|
||||
{
|
||||
s_Face = BeginPanel("Face", s_Face);
|
||||
if (s_Face)
|
||||
{
|
||||
DoFacePanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
|
||||
s_DebugExtended = BeginPanel("Debug Settings", s_DebugExtended);
|
||||
if (s_DebugExtended)
|
||||
{
|
||||
DoDebugPanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
}
|
||||
|
||||
void DoFacePanel()
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
if (m_Material.HasProperty(ShaderUtilities.ID_FaceTex))
|
||||
{
|
||||
DoColor("_FaceColor", "Color");
|
||||
DoTexture2D("_FaceTex", "Texture", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoColor("_Color", "Color");
|
||||
DoSlider("_DiffusePower", "Diffuse Power");
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel -= 1;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
void DoDebugPanel()
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
DoTexture2D("_MainTex", "Font Atlas");
|
||||
if (m_Material.HasProperty(ShaderUtilities.ID_VertexOffsetX))
|
||||
{
|
||||
if (m_Material.HasProperty(ShaderUtilities.ID_Padding))
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
DoFloat("_Padding", "Padding");
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
DoFloat("_VertexOffsetX", "Offset X");
|
||||
DoFloat("_VertexOffsetY", "Offset Y");
|
||||
}
|
||||
|
||||
if (m_Material.HasProperty(ShaderUtilities.ID_MaskSoftnessX))
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
DoFloat("_MaskSoftnessX", "Softness X");
|
||||
DoFloat("_MaskSoftnessY", "Softness Y");
|
||||
DoVector("_ClipRect", "Clip Rect", s_LbrtVectorLabels);
|
||||
}
|
||||
|
||||
if (m_Material.HasProperty(ShaderUtilities.ID_StencilID))
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
DoFloat("_Stencil", "Stencil ID");
|
||||
DoFloat("_StencilComp", "Stencil Comp");
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel -= 1;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 806de5a9211448c8b65c8435ebb48dd4
|
||||
timeCreated: 1469998850
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,237 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.TextCore;
|
||||
using UnityEngine.TextCore.LowLevel;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(TMP_Character))]
|
||||
public class TMP_CharacterPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
//[SerializeField]
|
||||
//static Material s_InternalSDFMaterial;
|
||||
|
||||
//[SerializeField]
|
||||
//static Material s_InternalBitmapMaterial;
|
||||
|
||||
int m_GlyphSelectedForEditing = -1;
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
SerializedProperty prop_Unicode = property.FindPropertyRelative("m_Unicode");
|
||||
SerializedProperty prop_GlyphIndex = property.FindPropertyRelative("m_GlyphIndex");
|
||||
SerializedProperty prop_Scale = property.FindPropertyRelative("m_Scale");
|
||||
|
||||
|
||||
GUIStyle style = new GUIStyle(EditorStyles.label);
|
||||
style.richText = true;
|
||||
|
||||
EditorGUIUtility.labelWidth = 40f;
|
||||
EditorGUIUtility.fieldWidth = 50;
|
||||
|
||||
Rect rect = new Rect(position.x + 50, position.y, position.width, 49);
|
||||
|
||||
// Display non-editable fields
|
||||
if (GUI.enabled == false)
|
||||
{
|
||||
int unicode = prop_Unicode.intValue;
|
||||
EditorGUI.LabelField(new Rect(rect.x, rect.y, 120f, 18), new GUIContent("Unicode: <color=#FFFF80>0x" + unicode.ToString("X") + "</color>"), style);
|
||||
EditorGUI.LabelField(new Rect(rect.x + 115, rect.y, 120f, 18), unicode <= 0xFFFF ? new GUIContent("UTF16: <color=#FFFF80>\\u" + unicode.ToString("X4") + "</color>") : new GUIContent("UTF32: <color=#FFFF80>\\U" + unicode.ToString("X8") + "</color>"), style);
|
||||
EditorGUI.LabelField(new Rect(rect.x, rect.y + 18, 120, 18), new GUIContent("Glyph ID: <color=#FFFF80>" + prop_GlyphIndex.intValue + "</color>"), style);
|
||||
EditorGUI.LabelField(new Rect(rect.x, rect.y + 36, 80, 18), new GUIContent("Scale: <color=#FFFF80>" + prop_Scale.floatValue + "</color>"), style);
|
||||
|
||||
// Draw Glyph (if exists)
|
||||
DrawGlyph(position, property);
|
||||
}
|
||||
else // Display editable fields
|
||||
{
|
||||
EditorGUIUtility.labelWidth = 55f;
|
||||
GUI.SetNextControlName("Unicode Input");
|
||||
EditorGUI.BeginChangeCheck();
|
||||
string unicode = EditorGUI.TextField(new Rect(rect.x, rect.y, 120, 18), "Unicode:", prop_Unicode.intValue.ToString("X"));
|
||||
|
||||
if (GUI.GetNameOfFocusedControl() == "Unicode Input")
|
||||
{
|
||||
//Filter out unwanted characters.
|
||||
char chr = Event.current.character;
|
||||
if ((chr < '0' || chr > '9') && (chr < 'a' || chr > 'f') && (chr < 'A' || chr > 'F'))
|
||||
{
|
||||
Event.current.character = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
// Update Unicode value
|
||||
prop_Unicode.intValue = TMP_TextUtilities.StringHexToInt(unicode);
|
||||
}
|
||||
|
||||
// Cache current glyph index in case it needs to be restored if the new glyph index is invalid.
|
||||
int currentGlyphIndex = prop_GlyphIndex.intValue;
|
||||
|
||||
EditorGUIUtility.labelWidth = 59f;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.DelayedIntField(new Rect(rect.x, rect.y + 18, 100, 18), prop_GlyphIndex, new GUIContent("Glyph ID:"));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
// Get a reference to the font asset
|
||||
TMP_FontAsset fontAsset = property.serializedObject.targetObject as TMP_FontAsset;
|
||||
|
||||
// Make sure new glyph index is valid.
|
||||
int elementIndex = fontAsset.glyphTable.FindIndex(item => item.index == prop_GlyphIndex.intValue);
|
||||
|
||||
if (elementIndex == -1)
|
||||
prop_GlyphIndex.intValue = currentGlyphIndex;
|
||||
else
|
||||
fontAsset.m_IsFontAssetLookupTablesDirty = true;
|
||||
}
|
||||
|
||||
int glyphIndex = prop_GlyphIndex.intValue;
|
||||
|
||||
// Reset glyph selection if new character has been selected.
|
||||
if (GUI.enabled && m_GlyphSelectedForEditing != glyphIndex)
|
||||
m_GlyphSelectedForEditing = -1;
|
||||
|
||||
// Display button to edit the glyph data.
|
||||
if (GUI.Button(new Rect(rect.x + 120, rect.y + 18, 75, 18), new GUIContent("Edit Glyph")))
|
||||
{
|
||||
if (m_GlyphSelectedForEditing == -1)
|
||||
m_GlyphSelectedForEditing = glyphIndex;
|
||||
else
|
||||
m_GlyphSelectedForEditing = -1;
|
||||
|
||||
// Button clicks should not result in potential change.
|
||||
GUI.changed = false;
|
||||
}
|
||||
|
||||
// Show the glyph property drawer if selected
|
||||
if (glyphIndex == m_GlyphSelectedForEditing && GUI.enabled)
|
||||
{
|
||||
// Get a reference to the font asset
|
||||
TMP_FontAsset fontAsset = property.serializedObject.targetObject as TMP_FontAsset;
|
||||
|
||||
if (fontAsset != null)
|
||||
{
|
||||
// Get the index of the glyph in the font asset glyph table.
|
||||
int elementIndex = fontAsset.glyphTable.FindIndex(item => item.index == glyphIndex);
|
||||
|
||||
if (elementIndex != -1)
|
||||
{
|
||||
SerializedProperty prop_GlyphTable = property.serializedObject.FindProperty("m_GlyphTable");
|
||||
SerializedProperty prop_Glyph = prop_GlyphTable.GetArrayElementAtIndex(elementIndex);
|
||||
|
||||
SerializedProperty prop_GlyphMetrics = prop_Glyph.FindPropertyRelative("m_Metrics");
|
||||
SerializedProperty prop_GlyphRect = prop_Glyph.FindPropertyRelative("m_GlyphRect");
|
||||
|
||||
Rect newRect = EditorGUILayout.GetControlRect(false, 115);
|
||||
EditorGUI.DrawRect(new Rect(newRect.x + 52, newRect.y - 20, newRect.width - 52, newRect.height - 5), new Color(0.1f, 0.1f, 0.1f, 0.45f));
|
||||
EditorGUI.DrawRect(new Rect(newRect.x + 53, newRect.y - 19, newRect.width - 54, newRect.height - 7), new Color(0.3f, 0.3f, 0.3f, 0.8f));
|
||||
|
||||
// Display GlyphRect
|
||||
newRect.x += 55;
|
||||
newRect.y -= 18;
|
||||
newRect.width += 5;
|
||||
EditorGUI.PropertyField(newRect, prop_GlyphRect);
|
||||
|
||||
// Display GlyphMetrics
|
||||
newRect.y += 45;
|
||||
EditorGUI.PropertyField(newRect, prop_GlyphMetrics);
|
||||
|
||||
rect.y += 120;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUIUtility.labelWidth = 39f;
|
||||
EditorGUI.PropertyField(new Rect(rect.x, rect.y + 36, 80, 18), prop_Scale, new GUIContent("Scale:"));
|
||||
|
||||
// Draw Glyph (if exists)
|
||||
DrawGlyph(position, property);
|
||||
}
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return 58;
|
||||
}
|
||||
|
||||
void DrawGlyph(Rect position, SerializedProperty property)
|
||||
{
|
||||
// Get a reference to the atlas texture
|
||||
TMP_FontAsset fontAsset = property.serializedObject.targetObject as TMP_FontAsset;
|
||||
|
||||
if (fontAsset == null)
|
||||
return;
|
||||
|
||||
// Get a reference to the Glyph Table
|
||||
SerializedProperty prop_GlyphTable = property.serializedObject.FindProperty("m_GlyphTable");
|
||||
int glyphIndex = property.FindPropertyRelative("m_GlyphIndex").intValue;
|
||||
int elementIndex = fontAsset.glyphTable.FindIndex(item => item.index == glyphIndex);
|
||||
|
||||
// Return if we can't find the glyph
|
||||
if (elementIndex == -1)
|
||||
return;
|
||||
|
||||
SerializedProperty prop_Glyph = prop_GlyphTable.GetArrayElementAtIndex(elementIndex);
|
||||
|
||||
// Get reference to atlas texture.
|
||||
int atlasIndex = prop_Glyph.FindPropertyRelative("m_AtlasIndex").intValue;
|
||||
Texture2D atlasTexture = fontAsset.atlasTextures.Length > atlasIndex ? fontAsset.atlasTextures[atlasIndex] : null;
|
||||
|
||||
if (atlasTexture == null)
|
||||
return;
|
||||
|
||||
Material mat;
|
||||
if (((GlyphRasterModes)fontAsset.atlasRenderMode & GlyphRasterModes.RASTER_MODE_BITMAP) == GlyphRasterModes.RASTER_MODE_BITMAP)
|
||||
{
|
||||
mat = TMP_FontAssetEditor.internalBitmapMaterial;
|
||||
|
||||
if (mat == null)
|
||||
return;
|
||||
|
||||
mat.mainTexture = atlasTexture;
|
||||
mat.SetColor("_Color", Color.white);
|
||||
}
|
||||
else
|
||||
{
|
||||
mat = TMP_FontAssetEditor.internalSDFMaterial;
|
||||
|
||||
if (mat == null)
|
||||
return;
|
||||
|
||||
mat.mainTexture = atlasTexture;
|
||||
mat.SetFloat(ShaderUtilities.ID_GradientScale, fontAsset.atlasPadding + 1);
|
||||
}
|
||||
|
||||
// Draw glyph
|
||||
Rect glyphDrawPosition = new Rect(position.x, position.y, 48, 58);
|
||||
|
||||
SerializedProperty prop_GlyphRect = prop_Glyph.FindPropertyRelative("m_GlyphRect");
|
||||
|
||||
int glyphOriginX = prop_GlyphRect.FindPropertyRelative("m_X").intValue;
|
||||
int glyphOriginY = prop_GlyphRect.FindPropertyRelative("m_Y").intValue;
|
||||
int glyphWidth = prop_GlyphRect.FindPropertyRelative("m_Width").intValue;
|
||||
int glyphHeight = prop_GlyphRect.FindPropertyRelative("m_Height").intValue;
|
||||
|
||||
float normalizedHeight = fontAsset.faceInfo.ascentLine - fontAsset.faceInfo.descentLine;
|
||||
float scale = glyphDrawPosition.width / normalizedHeight;
|
||||
|
||||
// Compute the normalized texture coordinates
|
||||
Rect texCoords = new Rect((float)glyphOriginX / atlasTexture.width, (float)glyphOriginY / atlasTexture.height, (float)glyphWidth / atlasTexture.width, (float)glyphHeight / atlasTexture.height);
|
||||
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
{
|
||||
glyphDrawPosition.x += (glyphDrawPosition.width - glyphWidth * scale) / 2;
|
||||
glyphDrawPosition.y += (glyphDrawPosition.height - glyphHeight * scale) / 2;
|
||||
glyphDrawPosition.width = glyphWidth * scale;
|
||||
glyphDrawPosition.height = glyphHeight * scale;
|
||||
|
||||
// Could switch to using the default material of the font asset which would require passing scale to the shader.
|
||||
Graphics.DrawTexture(glyphDrawPosition, atlasTexture, texCoords, 0, 0, 0, 0, new Color(1f, 1f, 1f), mat);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01ada73c4792aba4c937ff5d92cce866
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,51 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
public static class TMP_ColorGradientAssetMenu
|
||||
{
|
||||
[MenuItem("Assets/Create/TextMeshPro/Color Gradient", false, 115)]
|
||||
public static void CreateColorGradient(MenuCommand context)
|
||||
{
|
||||
string filePath;
|
||||
|
||||
if (Selection.assetGUIDs.Length == 0)
|
||||
filePath = "Assets/New TMP Color Gradient.asset";
|
||||
else
|
||||
filePath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);
|
||||
|
||||
if (Directory.Exists(filePath))
|
||||
{
|
||||
filePath += "/New TMP Color Gradient.asset";
|
||||
}
|
||||
else
|
||||
{
|
||||
filePath = Path.GetDirectoryName(filePath) + "/New TMP Color Gradient.asset";
|
||||
}
|
||||
|
||||
filePath = AssetDatabase.GenerateUniqueAssetPath(filePath);
|
||||
|
||||
// Create new Color Gradient Asset.
|
||||
TMP_ColorGradient colorGradient = ScriptableObject.CreateInstance<TMP_ColorGradient>();
|
||||
|
||||
// Create Asset
|
||||
AssetDatabase.CreateAsset(colorGradient, filePath);
|
||||
|
||||
//EditorUtility.SetDirty(colorGradient);
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(colorGradient));
|
||||
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = colorGradient;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9647b571c5e44729b71d756b3d55317
|
||||
timeCreated: 1468187791
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,146 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
[CustomEditor(typeof(TMP_ColorGradient))]
|
||||
public class TMP_ColorGradientEditor : Editor
|
||||
{
|
||||
SerializedProperty m_ColorMode;
|
||||
SerializedProperty m_TopLeftColor;
|
||||
SerializedProperty m_TopRightColor;
|
||||
SerializedProperty m_BottomLeftColor;
|
||||
SerializedProperty m_BottomRightColor;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_ColorMode = serializedObject.FindProperty("colorMode");
|
||||
m_TopLeftColor = serializedObject.FindProperty("topLeft");
|
||||
m_TopRightColor = serializedObject.FindProperty("topRight");
|
||||
m_BottomLeftColor = serializedObject.FindProperty("bottomLeft");
|
||||
m_BottomRightColor = serializedObject.FindProperty("bottomRight");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(m_ColorMode, new GUIContent("Color Mode"));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
switch ((ColorMode)m_ColorMode.enumValueIndex)
|
||||
{
|
||||
case ColorMode.Single:
|
||||
m_TopRightColor.colorValue = m_TopLeftColor.colorValue;
|
||||
m_BottomLeftColor.colorValue = m_TopLeftColor.colorValue;
|
||||
m_BottomRightColor.colorValue = m_TopLeftColor.colorValue;
|
||||
break;
|
||||
case ColorMode.HorizontalGradient:
|
||||
m_BottomLeftColor.colorValue = m_TopLeftColor.colorValue;
|
||||
m_BottomRightColor.colorValue = m_TopRightColor.colorValue;
|
||||
break;
|
||||
case ColorMode.VerticalGradient:
|
||||
m_TopRightColor.colorValue = m_TopLeftColor.colorValue;
|
||||
m_BottomRightColor.colorValue = m_BottomLeftColor.colorValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Rect rect;
|
||||
switch ((ColorMode)m_ColorMode.enumValueIndex)
|
||||
{
|
||||
case ColorMode.Single:
|
||||
EditorGUI.BeginChangeCheck();
|
||||
rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2));
|
||||
EditorGUI.PrefixLabel(rect, new GUIContent("Colors"));
|
||||
rect.x += EditorGUIUtility.labelWidth;
|
||||
rect.width = (rect.width - EditorGUIUtility.labelWidth) / (EditorGUIUtility.wideMode ? 1f : 2f);
|
||||
TMP_EditorUtility.DrawColorProperty(rect, m_TopLeftColor);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
m_TopRightColor.colorValue = m_TopLeftColor.colorValue;
|
||||
m_BottomLeftColor.colorValue = m_TopLeftColor.colorValue;
|
||||
m_BottomRightColor.colorValue = m_TopLeftColor.colorValue;
|
||||
}
|
||||
break;
|
||||
|
||||
case ColorMode.HorizontalGradient:
|
||||
rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2));
|
||||
EditorGUI.PrefixLabel(rect, new GUIContent("Colors"));
|
||||
rect.x += EditorGUIUtility.labelWidth;
|
||||
rect.width = (rect.width - EditorGUIUtility.labelWidth) / 2f;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
TMP_EditorUtility.DrawColorProperty(rect, m_TopLeftColor);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
m_BottomLeftColor.colorValue = m_TopLeftColor.colorValue;
|
||||
}
|
||||
|
||||
rect.x += rect.width;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
TMP_EditorUtility.DrawColorProperty(rect, m_TopRightColor);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
m_BottomRightColor.colorValue = m_TopRightColor.colorValue;
|
||||
}
|
||||
break;
|
||||
|
||||
case ColorMode.VerticalGradient:
|
||||
rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2));
|
||||
EditorGUI.PrefixLabel(rect, new GUIContent("Colors"));
|
||||
rect.x += EditorGUIUtility.labelWidth;
|
||||
rect.width = (rect.width - EditorGUIUtility.labelWidth) / (EditorGUIUtility.wideMode ? 1f : 2f);
|
||||
rect.height = EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
TMP_EditorUtility.DrawColorProperty(rect, m_TopLeftColor);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
m_TopRightColor.colorValue = m_TopLeftColor.colorValue;
|
||||
}
|
||||
|
||||
rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2));
|
||||
rect.x += EditorGUIUtility.labelWidth;
|
||||
rect.width = (rect.width - EditorGUIUtility.labelWidth) / (EditorGUIUtility.wideMode ? 1f : 2f);
|
||||
rect.height = EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
TMP_EditorUtility.DrawColorProperty(rect, m_BottomLeftColor);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
m_BottomRightColor.colorValue = m_BottomLeftColor.colorValue;
|
||||
}
|
||||
break;
|
||||
|
||||
case ColorMode.FourCornersGradient:
|
||||
rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2));
|
||||
EditorGUI.PrefixLabel(rect, new GUIContent("Colors"));
|
||||
rect.x += EditorGUIUtility.labelWidth;
|
||||
rect.width = (rect.width - EditorGUIUtility.labelWidth) / 2f;
|
||||
rect.height = EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2);
|
||||
|
||||
TMP_EditorUtility.DrawColorProperty(rect, m_TopLeftColor);
|
||||
rect.x += rect.width;
|
||||
TMP_EditorUtility.DrawColorProperty(rect, m_TopRightColor);
|
||||
|
||||
rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2));
|
||||
rect.x += EditorGUIUtility.labelWidth;
|
||||
rect.width = (rect.width - EditorGUIUtility.labelWidth) / 2f;
|
||||
rect.height = EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2);
|
||||
|
||||
TMP_EditorUtility.DrawColorProperty(rect, m_BottomLeftColor);
|
||||
rect.x += rect.width;
|
||||
TMP_EditorUtility.DrawColorProperty(rect, m_BottomRightColor);
|
||||
break;
|
||||
}
|
||||
|
||||
if (serializedObject.ApplyModifiedProperties())
|
||||
TMPro_EventManager.ON_COLOR_GRAIDENT_PROPERTY_CHANGED(target as TMP_ColorGradient);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fcc60c1d6bb544d9b712b652f418ff3a
|
||||
timeCreated: 1468400050
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,51 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UI;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
[CustomEditor(typeof(TMP_Dropdown), true)]
|
||||
[CanEditMultipleObjects]
|
||||
public class DropdownEditor : SelectableEditor
|
||||
{
|
||||
SerializedProperty m_Template;
|
||||
SerializedProperty m_CaptionText;
|
||||
SerializedProperty m_CaptionImage;
|
||||
SerializedProperty m_ItemText;
|
||||
SerializedProperty m_ItemImage;
|
||||
SerializedProperty m_OnSelectionChanged;
|
||||
SerializedProperty m_Value;
|
||||
SerializedProperty m_Options;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
m_Template = serializedObject.FindProperty("m_Template");
|
||||
m_CaptionText = serializedObject.FindProperty("m_CaptionText");
|
||||
m_CaptionImage = serializedObject.FindProperty("m_CaptionImage");
|
||||
m_ItemText = serializedObject.FindProperty("m_ItemText");
|
||||
m_ItemImage = serializedObject.FindProperty("m_ItemImage");
|
||||
m_OnSelectionChanged = serializedObject.FindProperty("m_OnValueChanged");
|
||||
m_Value = serializedObject.FindProperty("m_Value");
|
||||
m_Options = serializedObject.FindProperty("m_Options");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
EditorGUILayout.Space();
|
||||
|
||||
serializedObject.Update();
|
||||
EditorGUILayout.PropertyField(m_Template);
|
||||
EditorGUILayout.PropertyField(m_CaptionText);
|
||||
EditorGUILayout.PropertyField(m_CaptionImage);
|
||||
EditorGUILayout.PropertyField(m_ItemText);
|
||||
EditorGUILayout.PropertyField(m_ItemImage);
|
||||
EditorGUILayout.PropertyField(m_Value);
|
||||
EditorGUILayout.PropertyField(m_Options);
|
||||
EditorGUILayout.PropertyField(m_OnSelectionChanged);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6dbcf248c987476181a37f01a1814975
|
||||
timeCreated: 1446377461
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple implementation of coroutine working in the Unity Editor.
|
||||
/// </summary>
|
||||
public class TMP_EditorCoroutine
|
||||
{
|
||||
//private static Dictionary<int, EditorCoroutine> s_ActiveCoroutines;
|
||||
|
||||
readonly IEnumerator coroutine;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="routine"></param>
|
||||
TMP_EditorCoroutine(IEnumerator routine)
|
||||
{
|
||||
this.coroutine = routine;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Starts a new EditorCoroutine.
|
||||
/// </summary>
|
||||
/// <param name="newCoroutine">Coroutine</param>
|
||||
/// <returns>new EditorCoroutine</returns>
|
||||
public static TMP_EditorCoroutine StartCoroutine(IEnumerator routine)
|
||||
{
|
||||
TMP_EditorCoroutine coroutine = new TMP_EditorCoroutine(routine);
|
||||
coroutine.Start();
|
||||
|
||||
// Add coroutine to tracking list
|
||||
//if (s_ActiveCoroutines == null)
|
||||
// s_ActiveCoroutines = new Dictionary<int, EditorCoroutine>();
|
||||
|
||||
// Add new instance of editor coroutine to dictionary.
|
||||
//s_ActiveCoroutines.Add(coroutine.GetHashCode(), coroutine);
|
||||
|
||||
return coroutine;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clear delegate list
|
||||
/// </summary>
|
||||
//public static void StopAllEditorCoroutines()
|
||||
//{
|
||||
// EditorApplication.update = null;
|
||||
//}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Register callback for editor updates
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
EditorApplication.update += EditorUpdate;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Unregister callback for editor updates.
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
if (EditorApplication.update != null)
|
||||
EditorApplication.update -= EditorUpdate;
|
||||
|
||||
//s_ActiveCoroutines.Remove(this.GetHashCode());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Delegate function called on editor updates.
|
||||
/// </summary>
|
||||
void EditorUpdate()
|
||||
{
|
||||
// Stop editor coroutine if it does not continue.
|
||||
if (coroutine.MoveNext() == false)
|
||||
Stop();
|
||||
|
||||
// Process the different types of EditorCoroutines.
|
||||
if (coroutine.Current != null)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 27a0335dab59ec542aadd6636a5b4ebd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,153 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
[CustomEditor(typeof(TextMeshPro), true), CanEditMultipleObjects]
|
||||
public class TMP_EditorPanel : TMP_BaseEditorPanel
|
||||
{
|
||||
static readonly GUIContent k_SortingLayerLabel = new GUIContent("Sorting Layer", "Name of the Renderer's sorting layer.");
|
||||
static readonly GUIContent k_OrderInLayerLabel = new GUIContent("Order in Layer", "Renderer's order within a sorting layer.");
|
||||
static readonly GUIContent k_OrthographicLabel = new GUIContent("Orthographic Mode", "Should be enabled when using an orthographic camera. Instructs the shader to not perform any perspective correction.");
|
||||
static readonly GUIContent k_VolumetricLabel = new GUIContent("Volumetric Setup", "Use cubes rather than quads to render the text. Allows for volumetric rendering when combined with a compatible shader.");
|
||||
|
||||
SerializedProperty m_IsVolumetricTextProp;
|
||||
|
||||
SerializedProperty m_IsOrthographicProp;
|
||||
|
||||
Renderer m_Renderer;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
m_IsOrthographicProp = serializedObject.FindProperty("m_isOrthographic");
|
||||
|
||||
m_IsVolumetricTextProp = serializedObject.FindProperty("m_isVolumetricText");
|
||||
|
||||
m_Renderer = m_TextComponent.GetComponent<Renderer>();
|
||||
}
|
||||
|
||||
protected override void DrawExtraSettings()
|
||||
{
|
||||
Foldout.extraSettings = EditorGUILayout.Foldout(Foldout.extraSettings, k_ExtraSettingsLabel, true, TMP_UIStyleManager.boldFoldout);
|
||||
if (Foldout.extraSettings)
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
|
||||
DrawMargins();
|
||||
|
||||
DrawSortingLayer();
|
||||
|
||||
DrawGeometrySorting();
|
||||
|
||||
DrawOrthographicMode();
|
||||
|
||||
DrawRichText();
|
||||
|
||||
DrawParsing();
|
||||
|
||||
DrawVolumetricSetup();
|
||||
|
||||
DrawKerning();
|
||||
|
||||
DrawPadding();
|
||||
|
||||
EditorGUI.indentLevel -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawSortingLayer()
|
||||
{
|
||||
Undo.RecordObject(m_Renderer, "Sorting Layer Change");
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
// SORTING LAYERS
|
||||
var sortingLayerNames = SortingLayerHelper.sortingLayerNames;
|
||||
|
||||
var textComponent = (TextMeshPro)m_TextComponent;
|
||||
|
||||
// Look up the layer name using the current layer ID
|
||||
string oldName = SortingLayerHelper.GetSortingLayerNameFromID(textComponent.sortingLayerID);
|
||||
|
||||
// Use the name to look up our array index into the names list
|
||||
int oldLayerIndex = System.Array.IndexOf(sortingLayerNames, oldName);
|
||||
|
||||
// Show the pop-up for the names
|
||||
EditorGUIUtility.fieldWidth = 0f;
|
||||
int newLayerIndex = EditorGUILayout.Popup(k_SortingLayerLabel, oldLayerIndex, sortingLayerNames);
|
||||
|
||||
// If the index changes, look up the ID for the new index to store as the new ID
|
||||
if (newLayerIndex != oldLayerIndex)
|
||||
{
|
||||
textComponent.sortingLayerID = SortingLayerHelper.GetSortingLayerIDForIndex(newLayerIndex);
|
||||
}
|
||||
|
||||
// Expose the manual sorting order
|
||||
int newSortingLayerOrder = EditorGUILayout.IntField(k_OrderInLayerLabel, textComponent.sortingOrder);
|
||||
if (newSortingLayerOrder != textComponent.sortingOrder)
|
||||
{
|
||||
textComponent.sortingOrder = newSortingLayerOrder;
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
m_HavePropertiesChanged = true;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
protected void DrawOrthographicMode()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(m_IsOrthographicProp, k_OrthographicLabel);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
m_HavePropertiesChanged = true;
|
||||
}
|
||||
|
||||
protected void DrawVolumetricSetup()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(m_IsVolumetricTextProp, k_VolumetricLabel);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
m_HavePropertiesChanged = true;
|
||||
m_TextComponent.textInfo.ResetVertexLayout(m_IsVolumetricTextProp.boolValue);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
// Method to handle multi object selection
|
||||
protected override bool IsMixSelectionTypes()
|
||||
{
|
||||
GameObject[] objects = Selection.gameObjects;
|
||||
if (objects.Length > 1)
|
||||
{
|
||||
for (int i = 0; i < objects.Length; i++)
|
||||
{
|
||||
if (objects[i].GetComponent<TextMeshPro>() == null)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void OnUndoRedo()
|
||||
{
|
||||
int undoEventId = Undo.GetCurrentGroup();
|
||||
int lastUndoEventId = s_EventId;
|
||||
|
||||
if (undoEventId != lastUndoEventId)
|
||||
{
|
||||
for (int i = 0; i < targets.Length; i++)
|
||||
{
|
||||
//Debug.Log("Undo & Redo Performed detected in Editor Panel. Event ID:" + Undo.GetCurrentGroup());
|
||||
TMPro_EventManager.ON_TEXTMESHPRO_PROPERTY_CHANGED(true, targets[i] as TextMeshPro);
|
||||
s_EventId = undoEventId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34f6695d37a94370a3697f6b068f5d5e
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,450 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
public static class TMP_EditorUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the relative path of the package.
|
||||
/// </summary>
|
||||
public static string packageRelativePath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(m_PackagePath))
|
||||
m_PackagePath = GetPackageRelativePath();
|
||||
|
||||
return m_PackagePath;
|
||||
}
|
||||
}
|
||||
[SerializeField]
|
||||
private static string m_PackagePath;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the fully qualified path of the package.
|
||||
/// </summary>
|
||||
public static string packageFullPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(m_PackageFullPath))
|
||||
m_PackageFullPath = GetPackageFullPath();
|
||||
|
||||
return m_PackageFullPath;
|
||||
}
|
||||
}
|
||||
[SerializeField]
|
||||
private static string m_PackageFullPath;
|
||||
|
||||
|
||||
// Static Fields Related to locating the TextMesh Pro Asset
|
||||
private static string folderPath = "Not Found";
|
||||
|
||||
private static EditorWindow Gameview;
|
||||
private static bool isInitialized = false;
|
||||
|
||||
private static void GetGameview()
|
||||
{
|
||||
System.Reflection.Assembly assembly = typeof(UnityEditor.EditorWindow).Assembly;
|
||||
System.Type type = assembly.GetType("UnityEditor.GameView");
|
||||
Gameview = EditorWindow.GetWindow(type);
|
||||
}
|
||||
|
||||
|
||||
public static void RepaintAll()
|
||||
{
|
||||
if (isInitialized == false)
|
||||
{
|
||||
GetGameview();
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
SceneView.RepaintAll();
|
||||
Gameview.Repaint();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create and return a new asset in a smart location based on the current selection and then select it.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// Name of the new asset. Do not include the .asset extension.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The new asset.
|
||||
/// </returns>
|
||||
public static T CreateAsset<T>(string name) where T : ScriptableObject
|
||||
{
|
||||
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
|
||||
if (path.Length == 0)
|
||||
{
|
||||
// no asset selected, place in asset root
|
||||
path = "Assets/" + name + ".asset";
|
||||
}
|
||||
else if (Directory.Exists(path))
|
||||
{
|
||||
// place in currently selected directory
|
||||
path += "/" + name + ".asset";
|
||||
}
|
||||
else {
|
||||
// place in current selection's containing directory
|
||||
path = Path.GetDirectoryName(path) + "/" + name + ".asset";
|
||||
}
|
||||
T asset = ScriptableObject.CreateInstance<T>();
|
||||
AssetDatabase.CreateAsset(asset, AssetDatabase.GenerateUniqueAssetPath(path));
|
||||
EditorUtility.FocusProjectWindow();
|
||||
Selection.activeObject = asset;
|
||||
return asset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Function used to find all materials which reference a font atlas so we can update all their references.
|
||||
public static Material[] FindMaterialReferences(TMP_FontAsset fontAsset)
|
||||
{
|
||||
List<Material> refs = new List<Material>();
|
||||
Material mat = fontAsset.material;
|
||||
refs.Add(mat);
|
||||
|
||||
// Get materials matching the search pattern.
|
||||
string searchPattern = "t:Material" + " " + fontAsset.name.Split(new char[] { ' ' })[0];
|
||||
string[] materialAssetGUIDs = AssetDatabase.FindAssets(searchPattern);
|
||||
|
||||
for (int i = 0; i < materialAssetGUIDs.Length; i++)
|
||||
{
|
||||
string materialPath = AssetDatabase.GUIDToAssetPath(materialAssetGUIDs[i]);
|
||||
Material targetMaterial = AssetDatabase.LoadAssetAtPath<Material>(materialPath);
|
||||
|
||||
if (targetMaterial.HasProperty(ShaderUtilities.ID_MainTex) && targetMaterial.GetTexture(ShaderUtilities.ID_MainTex) != null && mat.GetTexture(ShaderUtilities.ID_MainTex) != null && targetMaterial.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID() == mat.GetTexture(ShaderUtilities.ID_MainTex).GetInstanceID())
|
||||
{
|
||||
if (!refs.Contains(targetMaterial))
|
||||
refs.Add(targetMaterial);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Find a more efficient method to unload resources.
|
||||
//Resources.UnloadAsset(targetMaterial.GetTexture(ShaderUtilities.ID_MainTex));
|
||||
}
|
||||
}
|
||||
|
||||
return refs.ToArray();
|
||||
}
|
||||
|
||||
|
||||
// Function used to find the Font Asset which matches the given Material Preset and Font Atlas Texture.
|
||||
public static TMP_FontAsset FindMatchingFontAsset(Material mat)
|
||||
{
|
||||
if (mat.GetTexture(ShaderUtilities.ID_MainTex) == null) return null;
|
||||
|
||||
// Find the dependent assets of this material.
|
||||
string[] dependentAssets = AssetDatabase.GetDependencies(AssetDatabase.GetAssetPath(mat), false);
|
||||
|
||||
for (int i = 0; i < dependentAssets.Length; i++)
|
||||
{
|
||||
TMP_FontAsset fontAsset = AssetDatabase.LoadAssetAtPath<TMP_FontAsset>(dependentAssets[i]);
|
||||
if (fontAsset != null)
|
||||
return fontAsset;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static string GetPackageRelativePath()
|
||||
{
|
||||
// Check for potential UPM package
|
||||
string packagePath = Path.GetFullPath("Packages/com.unity.textmeshpro");
|
||||
if (Directory.Exists(packagePath))
|
||||
{
|
||||
return "Packages/com.unity.textmeshpro";
|
||||
}
|
||||
|
||||
packagePath = Path.GetFullPath("Assets/..");
|
||||
if (Directory.Exists(packagePath))
|
||||
{
|
||||
// Search default location for development package
|
||||
if (Directory.Exists(packagePath + "/Assets/Packages/com.unity.TextMeshPro/Editor Resources"))
|
||||
{
|
||||
return "Assets/Packages/com.unity.TextMeshPro";
|
||||
}
|
||||
|
||||
// Search for default location of normal TextMesh Pro AssetStore package
|
||||
if (Directory.Exists(packagePath + "/Assets/TextMesh Pro/Editor Resources"))
|
||||
{
|
||||
return "Assets/TextMesh Pro";
|
||||
}
|
||||
|
||||
// Search for potential alternative locations in the user project
|
||||
string[] matchingPaths = Directory.GetDirectories(packagePath, "TextMesh Pro", SearchOption.AllDirectories);
|
||||
packagePath = ValidateLocation(matchingPaths, packagePath);
|
||||
if (packagePath != null) return packagePath;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetPackageFullPath()
|
||||
{
|
||||
// Check for potential UPM package
|
||||
string packagePath = Path.GetFullPath("Packages/com.unity.textmeshpro");
|
||||
if (Directory.Exists(packagePath))
|
||||
{
|
||||
return packagePath;
|
||||
}
|
||||
|
||||
packagePath = Path.GetFullPath("Assets/..");
|
||||
if (Directory.Exists(packagePath))
|
||||
{
|
||||
// Search default location for development package
|
||||
if (Directory.Exists(packagePath + "/Assets/Packages/com.unity.TextMeshPro/Editor Resources"))
|
||||
{
|
||||
return packagePath + "/Assets/Packages/com.unity.TextMeshPro";
|
||||
}
|
||||
|
||||
// Search for default location of normal TextMesh Pro AssetStore package
|
||||
if (Directory.Exists(packagePath + "/Assets/TextMesh Pro/Editor Resources"))
|
||||
{
|
||||
return packagePath + "/Assets/TextMesh Pro";
|
||||
}
|
||||
|
||||
// Search for potential alternative locations in the user project
|
||||
string[] matchingPaths = Directory.GetDirectories(packagePath, "TextMesh Pro", SearchOption.AllDirectories);
|
||||
string path = ValidateLocation(matchingPaths, packagePath);
|
||||
if (path != null) return packagePath + path;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Method to validate the location of the asset folder by making sure the GUISkins folder exists.
|
||||
/// </summary>
|
||||
/// <param name="paths"></param>
|
||||
/// <returns></returns>
|
||||
private static string ValidateLocation(string[] paths, string projectPath)
|
||||
{
|
||||
for (int i = 0; i < paths.Length; i++)
|
||||
{
|
||||
// Check if any of the matching directories contain a GUISkins directory.
|
||||
if (Directory.Exists(paths[i] + "/Editor Resources"))
|
||||
{
|
||||
folderPath = paths[i].Replace(projectPath, "");
|
||||
folderPath = folderPath.TrimStart('\\', '/');
|
||||
return folderPath;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Function which returns a string containing a sequence of Decimal character ranges.
|
||||
/// </summary>
|
||||
/// <param name="characterSet"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDecimalCharacterSequence(int[] characterSet)
|
||||
{
|
||||
if (characterSet == null || characterSet.Length == 0)
|
||||
return string.Empty;
|
||||
|
||||
string characterSequence = string.Empty;
|
||||
int count = characterSet.Length;
|
||||
int first = characterSet[0];
|
||||
int last = first;
|
||||
|
||||
for (int i = 1; i < count; i++)
|
||||
{
|
||||
if (characterSet[i - 1] + 1 == characterSet[i])
|
||||
{
|
||||
last = characterSet[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (first == last)
|
||||
characterSequence += first + ",";
|
||||
else
|
||||
characterSequence += first + "-" + last + ",";
|
||||
|
||||
first = last = characterSet[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// handle the final group
|
||||
if (first == last)
|
||||
characterSequence += first;
|
||||
else
|
||||
characterSequence += first + "-" + last;
|
||||
|
||||
return characterSequence;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Function which returns a string containing a sequence of Unicode (Hex) character ranges.
|
||||
/// </summary>
|
||||
/// <param name="characterSet"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetUnicodeCharacterSequence(int[] characterSet)
|
||||
{
|
||||
if (characterSet == null || characterSet.Length == 0)
|
||||
return string.Empty;
|
||||
|
||||
string characterSequence = string.Empty;
|
||||
int count = characterSet.Length;
|
||||
int first = characterSet[0];
|
||||
int last = first;
|
||||
|
||||
for (int i = 1; i < count; i++)
|
||||
{
|
||||
if (characterSet[i - 1] + 1 == characterSet[i])
|
||||
{
|
||||
last = characterSet[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (first == last)
|
||||
characterSequence += first.ToString("X2") + ",";
|
||||
else
|
||||
characterSequence += first.ToString("X2") + "-" + last.ToString("X2") + ",";
|
||||
|
||||
first = last = characterSet[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// handle the final group
|
||||
if (first == last)
|
||||
characterSequence += first.ToString("X2");
|
||||
else
|
||||
characterSequence += first.ToString("X2") + "-" + last.ToString("X2");
|
||||
|
||||
return characterSequence;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="rect"></param>
|
||||
/// <param name="thickness"></param>
|
||||
/// <param name="color"></param>
|
||||
public static void DrawBox(Rect rect, float thickness, Color color)
|
||||
{
|
||||
EditorGUI.DrawRect(new Rect(rect.x - thickness, rect.y + thickness, rect.width + thickness * 2, thickness), color);
|
||||
EditorGUI.DrawRect(new Rect(rect.x - thickness, rect.y + thickness, thickness, rect.height - thickness * 2), color);
|
||||
EditorGUI.DrawRect(new Rect(rect.x - thickness, rect.y + rect.height - thickness * 2, rect.width + thickness * 2, thickness), color);
|
||||
EditorGUI.DrawRect(new Rect(rect.x + rect.width, rect.y + thickness, thickness, rect.height - thickness * 2), color);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Function to return the horizontal alignment grid value.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static int GetHorizontalAlignmentGridValue(int value)
|
||||
{
|
||||
if ((value & 0x1) == 0x1)
|
||||
return 0;
|
||||
else if ((value & 0x2) == 0x2)
|
||||
return 1;
|
||||
else if ((value & 0x4) == 0x4)
|
||||
return 2;
|
||||
else if ((value & 0x8) == 0x8)
|
||||
return 3;
|
||||
else if ((value & 0x10) == 0x10)
|
||||
return 4;
|
||||
else if ((value & 0x20) == 0x20)
|
||||
return 5;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function to return the vertical alignment grid value.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static int GetVerticalAlignmentGridValue(int value)
|
||||
{
|
||||
if ((value & 0x100) == 0x100)
|
||||
return 0;
|
||||
if ((value & 0x200) == 0x200)
|
||||
return 1;
|
||||
if ((value & 0x400) == 0x400)
|
||||
return 2;
|
||||
if ((value & 0x800) == 0x800)
|
||||
return 3;
|
||||
if ((value & 0x1000) == 0x1000)
|
||||
return 4;
|
||||
if ((value & 0x2000) == 0x2000)
|
||||
return 5;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void DrawColorProperty(Rect rect, SerializedProperty property)
|
||||
{
|
||||
int oldIndent = EditorGUI.indentLevel;
|
||||
EditorGUI.indentLevel = 0;
|
||||
if (EditorGUIUtility.wideMode)
|
||||
{
|
||||
EditorGUI.PropertyField(new Rect(rect.x, rect.y, 50f, rect.height), property, GUIContent.none);
|
||||
rect.x += 50f;
|
||||
rect.width = Mathf.Min(100f, rect.width - 55f);
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.height /= 2f;
|
||||
rect.width = Mathf.Min(100f, rect.width - 5f);
|
||||
EditorGUI.PropertyField(rect, property, GUIContent.none);
|
||||
rect.y += rect.height;
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
string colorString = EditorGUI.TextField(rect, string.Format("#{0}", ColorUtility.ToHtmlStringRGBA(property.colorValue)));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (ColorUtility.TryParseHtmlString(colorString, out Color color))
|
||||
{
|
||||
property.colorValue = color;
|
||||
}
|
||||
}
|
||||
EditorGUI.indentLevel = oldIndent;
|
||||
}
|
||||
|
||||
public static bool EditorToggle(Rect position, bool value, GUIContent content, GUIStyle style)
|
||||
{
|
||||
var id = GUIUtility.GetControlID(content, FocusType.Keyboard, position);
|
||||
var evt = Event.current;
|
||||
|
||||
// Toggle selected toggle on space or return key
|
||||
if (GUIUtility.keyboardControl == id && evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Space || evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter))
|
||||
{
|
||||
value = !value;
|
||||
evt.Use();
|
||||
GUI.changed = true;
|
||||
}
|
||||
|
||||
if (evt.type == EventType.MouseDown && position.Contains(Event.current.mousePosition))
|
||||
{
|
||||
GUIUtility.keyboardControl = id;
|
||||
EditorGUIUtility.editingTextField = false;
|
||||
HandleUtility.Repaint();
|
||||
}
|
||||
|
||||
return GUI.Toggle(position, id, value, content, style);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2300e75732d74890b38a8ff257a3ae15
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96b44f7d98314b139324a8a87eb66067
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,190 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.TextCore;
|
||||
using UnityEngine.TextCore.LowLevel;
|
||||
using TMPro;
|
||||
|
||||
|
||||
namespace TMPro
|
||||
{
|
||||
public static class TMP_FontAsset_CreationMenu
|
||||
{
|
||||
/*
|
||||
[MenuItem("Assets/Create/TextMeshPro/Font Asset Fallback", false, 105)]
|
||||
public static void CreateFallbackFontAsset()
|
||||
{
|
||||
Object target = Selection.activeObject;
|
||||
|
||||
// Make sure the selection is a font file
|
||||
if (target == null || target.GetType() != typeof(TMP_FontAsset))
|
||||
{
|
||||
Debug.LogWarning("A Font file must first be selected in order to create a Font Asset.");
|
||||
return;
|
||||
}
|
||||
|
||||
TMP_FontAsset sourceFontAsset = (TMP_FontAsset)target;
|
||||
|
||||
string sourceFontFilePath = AssetDatabase.GetAssetPath(target);
|
||||
|
||||
string folderPath = Path.GetDirectoryName(sourceFontFilePath);
|
||||
string assetName = Path.GetFileNameWithoutExtension(sourceFontFilePath);
|
||||
|
||||
string newAssetFilePathWithName = AssetDatabase.GenerateUniqueAssetPath(folderPath + "/" + assetName + " - Fallback.asset");
|
||||
|
||||
//// Create new TM Font Asset.
|
||||
TMP_FontAsset fontAsset = ScriptableObject.CreateInstance<TMP_FontAsset>();
|
||||
AssetDatabase.CreateAsset(fontAsset, newAssetFilePathWithName);
|
||||
|
||||
fontAsset.version = "1.1.0";
|
||||
|
||||
fontAsset.faceInfo = sourceFontAsset.faceInfo;
|
||||
|
||||
fontAsset.m_SourceFontFileGUID = sourceFontAsset.m_SourceFontFileGUID;
|
||||
fontAsset.m_SourceFontFile_EditorRef = sourceFontAsset.m_SourceFontFile_EditorRef;
|
||||
fontAsset.atlasPopulationMode = TMP_FontAsset.AtlasPopulationMode.Dynamic;
|
||||
|
||||
int atlasWidth = fontAsset.atlasWidth = sourceFontAsset.atlasWidth;
|
||||
int atlasHeight = fontAsset.atlasHeight = sourceFontAsset.atlasHeight;
|
||||
int atlasPadding = fontAsset.atlasPadding = sourceFontAsset.atlasPadding;
|
||||
fontAsset.atlasRenderMode = sourceFontAsset.atlasRenderMode;
|
||||
|
||||
// Initialize array for the font atlas textures.
|
||||
fontAsset.atlasTextures = new Texture2D[1];
|
||||
|
||||
// Create and add font atlas texture
|
||||
Texture2D texture = new Texture2D(atlasWidth, atlasHeight, TextureFormat.Alpha8, false);
|
||||
Color32[] colors = new Color32[atlasWidth * atlasHeight];
|
||||
texture.SetPixels32(colors);
|
||||
|
||||
texture.name = assetName + " Atlas";
|
||||
fontAsset.atlasTextures[0] = texture;
|
||||
AssetDatabase.AddObjectToAsset(texture, fontAsset);
|
||||
|
||||
// Add free rectangle of the size of the texture.
|
||||
int packingModifier = ((GlyphRasterModes)fontAsset.atlasRenderMode & GlyphRasterModes.RASTER_MODE_BITMAP) == GlyphRasterModes.RASTER_MODE_BITMAP ? 0 : 1;
|
||||
fontAsset.m_FreeGlyphRects = new List<GlyphRect>() { new GlyphRect(0, 0, atlasWidth - packingModifier, atlasHeight - packingModifier) };
|
||||
fontAsset.m_UsedGlyphRects = new List<GlyphRect>();
|
||||
|
||||
// Create new Material and Add it as Sub-Asset
|
||||
Material tmp_material = new Material(sourceFontAsset.material);
|
||||
|
||||
tmp_material.name = texture.name + " Material";
|
||||
tmp_material.SetTexture(ShaderUtilities.ID_MainTex, texture);
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_TextureWidth, atlasWidth);
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_TextureHeight, atlasHeight);
|
||||
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_GradientScale, atlasPadding + packingModifier);
|
||||
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_WeightNormal, fontAsset.normalStyle);
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_WeightBold, fontAsset.boldStyle);
|
||||
|
||||
fontAsset.material = tmp_material;
|
||||
|
||||
AssetDatabase.AddObjectToAsset(tmp_material, fontAsset);
|
||||
|
||||
// Add Font Asset Creation Settings
|
||||
// TODO
|
||||
|
||||
// Not sure if this is still necessary in newer versions of Unity.
|
||||
EditorUtility.SetDirty(fontAsset);
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
*/
|
||||
|
||||
//[MenuItem("Assets/Create/TextMeshPro/Font Asset #%F12", true)]
|
||||
//public static bool CreateFontAssetMenuValidation()
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
|
||||
[MenuItem("Assets/Create/TextMeshPro/Font Asset #%F12", false, 100)]
|
||||
public static void CreateFontAsset()
|
||||
{
|
||||
Object target = Selection.activeObject;
|
||||
|
||||
// Make sure the selection is a font file
|
||||
if (target == null || target.GetType() != typeof(Font))
|
||||
{
|
||||
Debug.LogWarning("A Font file must first be selected in order to create a Font Asset.");
|
||||
return;
|
||||
}
|
||||
|
||||
Font sourceFont = (Font)target;
|
||||
|
||||
string sourceFontFilePath = AssetDatabase.GetAssetPath(target);
|
||||
|
||||
string folderPath = Path.GetDirectoryName(sourceFontFilePath);
|
||||
string assetName = Path.GetFileNameWithoutExtension(sourceFontFilePath);
|
||||
|
||||
string newAssetFilePathWithName = AssetDatabase.GenerateUniqueAssetPath(folderPath + "/" + assetName + " SDF.asset");
|
||||
|
||||
//// Create new TM Font Asset.
|
||||
TMP_FontAsset fontAsset = ScriptableObject.CreateInstance<TMP_FontAsset>();
|
||||
AssetDatabase.CreateAsset(fontAsset, newAssetFilePathWithName);
|
||||
|
||||
fontAsset.version = "1.1.0";
|
||||
|
||||
// Set face information
|
||||
FontEngine.InitializeFontEngine();
|
||||
FontEngine.LoadFontFace(sourceFont, 90);
|
||||
fontAsset.faceInfo = FontEngine.GetFaceInfo();
|
||||
|
||||
// Set font reference and GUID
|
||||
fontAsset.m_SourceFontFileGUID = AssetDatabase.AssetPathToGUID(sourceFontFilePath);
|
||||
fontAsset.m_SourceFontFile_EditorRef = sourceFont;
|
||||
fontAsset.atlasPopulationMode = AtlasPopulationMode.Dynamic;
|
||||
|
||||
// Default atlas resolution is 1024 x 1024.
|
||||
int atlasWidth = fontAsset.atlasWidth = 1024;
|
||||
int atlasHeight = fontAsset.atlasHeight = 1024;
|
||||
int atlasPadding = fontAsset.atlasPadding = 9;
|
||||
fontAsset.atlasRenderMode = GlyphRenderMode.SDFAA;
|
||||
|
||||
// Initialize array for the font atlas textures.
|
||||
fontAsset.atlasTextures = new Texture2D[1];
|
||||
|
||||
// Create atlas texture of size zero.
|
||||
Texture2D texture = new Texture2D(0, 0, TextureFormat.Alpha8, false);
|
||||
|
||||
texture.name = assetName + " Atlas";
|
||||
fontAsset.atlasTextures[0] = texture;
|
||||
AssetDatabase.AddObjectToAsset(texture, fontAsset);
|
||||
|
||||
// Add free rectangle of the size of the texture.
|
||||
int packingModifier = ((GlyphRasterModes)fontAsset.atlasRenderMode & GlyphRasterModes.RASTER_MODE_BITMAP) == GlyphRasterModes.RASTER_MODE_BITMAP ? 0 : 1;
|
||||
fontAsset.freeGlyphRects = new List<GlyphRect>() { new GlyphRect(0, 0, atlasWidth - packingModifier, atlasHeight - packingModifier) };
|
||||
fontAsset.usedGlyphRects = new List<GlyphRect>();
|
||||
|
||||
// Create new Material and Add it as Sub-Asset
|
||||
Shader default_Shader = Shader.Find("TextMeshPro/Distance Field");
|
||||
Material tmp_material = new Material(default_Shader);
|
||||
|
||||
tmp_material.name = texture.name + " Material";
|
||||
tmp_material.SetTexture(ShaderUtilities.ID_MainTex, texture);
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_TextureWidth, atlasWidth);
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_TextureHeight, atlasHeight);
|
||||
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_GradientScale, atlasPadding + packingModifier);
|
||||
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_WeightNormal, fontAsset.normalStyle);
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_WeightBold, fontAsset.boldStyle);
|
||||
|
||||
fontAsset.material = tmp_material;
|
||||
|
||||
AssetDatabase.AddObjectToAsset(tmp_material, fontAsset);
|
||||
|
||||
// Add Font Asset Creation Settings
|
||||
fontAsset.creationSettings = new FontAssetCreationSettings(fontAsset.m_SourceFontFileGUID, fontAsset.faceInfo.pointSize, 0, atlasPadding, 0, 1024, 1024, 7, string.Empty, (int)GlyphRenderMode.SDFAA);
|
||||
|
||||
// Not sure if this is still necessary in newer versions of Unity.
|
||||
EditorUtility.SetDirty(fontAsset);
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7496af95dfe67cf429ac65edaaf99106
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,382 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.TextCore;
|
||||
using UnityEngine.TextCore.LowLevel;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
[CustomPropertyDrawer(typeof(TMP_GlyphPairAdjustmentRecord))]
|
||||
public class TMP_GlyphPairAdjustmentRecordPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
private bool isEditingEnabled = false;
|
||||
private bool isSelectable = false;
|
||||
|
||||
private string m_FirstCharacter = string.Empty;
|
||||
private string m_SecondCharacter = string.Empty;
|
||||
private string m_PreviousInput;
|
||||
|
||||
static GUIContent s_CharacterTextFieldLabel = new GUIContent("Char:", "Enter the character or its UTF16 or UTF32 Unicode character escape sequence. For UTF16 use \"\\uFF00\" and for UTF32 use \"\\UFF00FF00\" representation.");
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
SerializedProperty prop_FirstAdjustmentRecord = property.FindPropertyRelative("m_FirstAdjustmentRecord");
|
||||
SerializedProperty prop_SecondAdjustmentRecord = property.FindPropertyRelative("m_SecondAdjustmentRecord");
|
||||
|
||||
SerializedProperty prop_FirstGlyphIndex = prop_FirstAdjustmentRecord.FindPropertyRelative("m_GlyphIndex");
|
||||
SerializedProperty prop_FirstGlyphValueRecord = prop_FirstAdjustmentRecord.FindPropertyRelative("m_GlyphValueRecord");
|
||||
|
||||
SerializedProperty prop_SecondGlyphIndex = prop_SecondAdjustmentRecord.FindPropertyRelative("m_GlyphIndex");
|
||||
SerializedProperty prop_SecondGlyphValueRecord = prop_SecondAdjustmentRecord.FindPropertyRelative("m_GlyphValueRecord");
|
||||
|
||||
SerializedProperty prop_FontFeatureLookupFlags = property.FindPropertyRelative("m_FeatureLookupFlags");
|
||||
|
||||
position.yMin += 2;
|
||||
|
||||
float width = position.width / 2;
|
||||
float padding = 5.0f;
|
||||
|
||||
Rect rect;
|
||||
|
||||
isEditingEnabled = GUI.enabled;
|
||||
isSelectable = label.text == "Selectable" ? true : false;
|
||||
|
||||
if (isSelectable)
|
||||
GUILayoutUtility.GetRect(position.width, 75);
|
||||
else
|
||||
GUILayoutUtility.GetRect(position.width, 55);
|
||||
|
||||
GUIStyle style = new GUIStyle(EditorStyles.label);
|
||||
style.richText = true;
|
||||
|
||||
// First Glyph
|
||||
GUI.enabled = isEditingEnabled;
|
||||
if (isSelectable)
|
||||
{
|
||||
rect = new Rect(position.x + 70, position.y, position.width, 49);
|
||||
|
||||
float labelWidth = GUI.skin.label.CalcSize(new GUIContent("ID: " + prop_FirstGlyphIndex.intValue)).x;
|
||||
EditorGUI.LabelField(new Rect(position.x + (64 - labelWidth) / 2, position.y + 60, 64f, 18f), new GUIContent("ID: <color=#FFFF80>" + prop_FirstGlyphIndex.intValue + "</color>"), style);
|
||||
|
||||
GUI.enabled = isEditingEnabled;
|
||||
EditorGUIUtility.labelWidth = 30f;
|
||||
|
||||
rect = new Rect(position.x + 70, position.y + 10, (width - 70) - padding, 18);
|
||||
EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_XPlacement"), new GUIContent("OX:"));
|
||||
|
||||
rect.y += 20;
|
||||
EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_YPlacement"), new GUIContent("OY:"));
|
||||
|
||||
rect.y += 20;
|
||||
EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_XAdvance"), new GUIContent("AX:"));
|
||||
|
||||
//rect.y += 20;
|
||||
//EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_YAdvance"), new GUIContent("AY:"));
|
||||
|
||||
DrawGlyph((uint)prop_FirstGlyphIndex.intValue, new Rect(position.x, position.y, position.width, position.height), property);
|
||||
}
|
||||
else
|
||||
{
|
||||
rect = new Rect(position.x, position.y, width / 2 * 0.8f - padding, 18);
|
||||
EditorGUIUtility.labelWidth = 40f;
|
||||
|
||||
// First Character Lookup
|
||||
GUI.SetNextControlName("FirstCharacterField");
|
||||
EditorGUI.BeginChangeCheck();
|
||||
string firstCharacter = EditorGUI.TextField(rect, s_CharacterTextFieldLabel, m_FirstCharacter);
|
||||
|
||||
if (GUI.GetNameOfFocusedControl() == "FirstCharacterField")
|
||||
{
|
||||
if (ValidateInput(firstCharacter))
|
||||
{
|
||||
//Debug.Log("1st Unicode value: [" + firstCharacter + "]");
|
||||
|
||||
uint unicode = GetUnicodeCharacter(firstCharacter);
|
||||
|
||||
// Lookup glyph index
|
||||
TMP_SerializedPropertyHolder propertyHolder = property.serializedObject.targetObject as TMP_SerializedPropertyHolder;
|
||||
TMP_FontAsset fontAsset = propertyHolder.fontAsset;
|
||||
if (fontAsset != null)
|
||||
{
|
||||
prop_FirstGlyphIndex.intValue = (int)fontAsset.GetGlyphIndex(unicode);
|
||||
propertyHolder.firstCharacter = unicode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
m_FirstCharacter = firstCharacter;
|
||||
|
||||
// First Glyph Index
|
||||
rect.x += width / 2 * 0.8f;
|
||||
|
||||
EditorGUIUtility.labelWidth = 25f;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.PropertyField(rect, prop_FirstGlyphIndex, new GUIContent("ID:"));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GUI.enabled = isEditingEnabled;
|
||||
EditorGUIUtility.labelWidth = 25f;
|
||||
|
||||
rect = new Rect(position.x, position.y + 20, width * 0.5f - padding, 18);
|
||||
EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_XPlacement"), new GUIContent("OX"));
|
||||
|
||||
rect.x += width * 0.5f;
|
||||
EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_YPlacement"), new GUIContent("OY"));
|
||||
|
||||
rect.x = position.x;
|
||||
rect.y += 20;
|
||||
EditorGUI.PropertyField(rect, prop_FirstGlyphValueRecord.FindPropertyRelative("m_XAdvance"), new GUIContent("AX"));
|
||||
|
||||
//rect.x += width * 0.5f;
|
||||
//EditorGUI.PropertyField(rect, prop_FirstGlyphAdjustment.FindPropertyRelative("m_YAdvance"), new GUIContent("AY"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Second Glyph
|
||||
GUI.enabled = isEditingEnabled;
|
||||
if (isSelectable)
|
||||
{
|
||||
float labelWidth = GUI.skin.label.CalcSize(new GUIContent("ID: " + prop_SecondGlyphIndex.intValue)).x;
|
||||
EditorGUI.LabelField(new Rect(position.width / 2 + 20 + (64 - labelWidth) / 2, position.y + 60, 64f, 18f), new GUIContent("ID: <color=#FFFF80>" + prop_SecondGlyphIndex.intValue + "</color>"), style);
|
||||
|
||||
GUI.enabled = isEditingEnabled;
|
||||
EditorGUIUtility.labelWidth = 30f;
|
||||
|
||||
rect = new Rect(position.width / 2 + 20 + 70, position.y + 10, (width - 70) - padding, 18);
|
||||
EditorGUI.PropertyField(rect, prop_SecondGlyphValueRecord.FindPropertyRelative("m_XPlacement"), new GUIContent("OX:"));
|
||||
|
||||
rect.y += 20;
|
||||
EditorGUI.PropertyField(rect, prop_SecondGlyphValueRecord.FindPropertyRelative("m_YPlacement"), new GUIContent("OY:"));
|
||||
|
||||
rect.y += 20;
|
||||
EditorGUI.PropertyField(rect, prop_SecondGlyphValueRecord.FindPropertyRelative("m_XAdvance"), new GUIContent("AX:"));
|
||||
|
||||
//rect.y += 20;
|
||||
//EditorGUI.PropertyField(rect, prop_SecondGlyphAdjustment.FindPropertyRelative("m_YAdvance"), new GUIContent("AY"));
|
||||
|
||||
DrawGlyph((uint)prop_SecondGlyphIndex.intValue, new Rect(position.width / 2 + 20, position.y, position.width, position.height), property);
|
||||
}
|
||||
else
|
||||
{
|
||||
rect = new Rect(position.width / 2 + 20, position.y, width / 2 * 0.8f - padding, 18);
|
||||
EditorGUIUtility.labelWidth = 40f;
|
||||
|
||||
// Second Character Lookup
|
||||
GUI.SetNextControlName("SecondCharacterField");
|
||||
EditorGUI.BeginChangeCheck();
|
||||
string secondCharacter = EditorGUI.TextField(rect, s_CharacterTextFieldLabel, m_SecondCharacter);
|
||||
|
||||
if (GUI.GetNameOfFocusedControl() == "SecondCharacterField")
|
||||
{
|
||||
if (ValidateInput(secondCharacter))
|
||||
{
|
||||
//Debug.Log("2nd Unicode value: [" + secondCharacter + "]");
|
||||
|
||||
uint unicode = GetUnicodeCharacter(secondCharacter);
|
||||
|
||||
// Lookup glyph index
|
||||
TMP_SerializedPropertyHolder propertyHolder = property.serializedObject.targetObject as TMP_SerializedPropertyHolder;
|
||||
TMP_FontAsset fontAsset = propertyHolder.fontAsset;
|
||||
if (fontAsset != null)
|
||||
{
|
||||
prop_SecondGlyphIndex.intValue = (int)fontAsset.GetGlyphIndex(unicode);
|
||||
propertyHolder.secondCharacter = unicode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
m_SecondCharacter = secondCharacter;
|
||||
|
||||
// Second Glyph Index
|
||||
rect.x += width / 2 * 0.8f;
|
||||
|
||||
EditorGUIUtility.labelWidth = 25f;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.PropertyField(rect, prop_SecondGlyphIndex, new GUIContent("ID:"));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GUI.enabled = isEditingEnabled;
|
||||
EditorGUIUtility.labelWidth = 25f;
|
||||
|
||||
rect = new Rect(position.width / 2 + 20, position.y + 20, width * 0.5f - padding, 18);
|
||||
EditorGUI.PropertyField(rect, prop_SecondGlyphValueRecord.FindPropertyRelative("m_XPlacement"), new GUIContent("OX"));
|
||||
|
||||
rect.x += width * 0.5f;
|
||||
EditorGUI.PropertyField(rect, prop_SecondGlyphValueRecord.FindPropertyRelative("m_YPlacement"), new GUIContent("OY"));
|
||||
|
||||
rect.x = position.width / 2 + 20;
|
||||
rect.y += 20;
|
||||
EditorGUI.PropertyField(rect, prop_SecondGlyphValueRecord.FindPropertyRelative("m_XAdvance"), new GUIContent("AX"));
|
||||
|
||||
//rect.x += width * 0.5f;
|
||||
//EditorGUI.PropertyField(rect, prop_SecondGlyphAdjustment.FindPropertyRelative("m_YAdvance"), new GUIContent("AY"));
|
||||
}
|
||||
|
||||
// Font Feature Lookup Flags
|
||||
if (isSelectable)
|
||||
{
|
||||
EditorGUIUtility.labelWidth = 55f;
|
||||
|
||||
rect.x = position.width - 255;
|
||||
rect.y += 23;
|
||||
rect.width = 270; // width - 70 - padding;
|
||||
|
||||
FontFeatureLookupFlags flags = (FontFeatureLookupFlags)prop_FontFeatureLookupFlags.intValue;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
flags = (FontFeatureLookupFlags)EditorGUI.EnumFlagsField(rect, new GUIContent("Options:"), flags);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
prop_FontFeatureLookupFlags.intValue = (int)flags;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool ValidateInput(string source)
|
||||
{
|
||||
int length = string.IsNullOrEmpty(source) ? 0 : source.Length;
|
||||
|
||||
////Filter out unwanted characters.
|
||||
Event evt = Event.current;
|
||||
|
||||
char c = evt.character;
|
||||
|
||||
if (c != '\0')
|
||||
{
|
||||
switch (length)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
if (source != m_PreviousInput)
|
||||
return true;
|
||||
|
||||
if ((source[0] == '\\' && (c == 'u' || c == 'U')) == false)
|
||||
evt.character = '\0';
|
||||
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
if ((c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F'))
|
||||
evt.character = '\0';
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
if (source[1] == 'u' || (c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F'))
|
||||
evt.character = '\0';
|
||||
|
||||
// Validate input
|
||||
if (length == 6 && source[1] == 'u' && source != m_PreviousInput)
|
||||
return true;
|
||||
break;
|
||||
case 10:
|
||||
if (source != m_PreviousInput)
|
||||
return true;
|
||||
|
||||
evt.character = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_PreviousInput = source;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint GetUnicodeCharacter (string source)
|
||||
{
|
||||
uint unicode;
|
||||
|
||||
if (source.Length == 1)
|
||||
unicode = source[0];
|
||||
else if (source.Length == 6)
|
||||
unicode = (uint)TMP_TextUtilities.StringHexToInt(source.Replace("\\u", ""));
|
||||
else
|
||||
unicode = (uint)TMP_TextUtilities.StringHexToInt(source.Replace("\\U", ""));
|
||||
|
||||
return unicode;
|
||||
}
|
||||
|
||||
void DrawGlyph(uint glyphIndex, Rect position, SerializedProperty property)
|
||||
{
|
||||
// Get a reference to the sprite texture
|
||||
TMP_FontAsset fontAsset = property.serializedObject.targetObject as TMP_FontAsset;
|
||||
|
||||
if (fontAsset == null)
|
||||
return;
|
||||
|
||||
// Check if glyph currently exists in the atlas texture.
|
||||
if (!fontAsset.glyphLookupTable.TryGetValue(glyphIndex, out Glyph glyph))
|
||||
return;
|
||||
|
||||
// Get reference to atlas texture.
|
||||
int atlasIndex = fontAsset.m_AtlasTextureIndex;
|
||||
Texture2D atlasTexture = fontAsset.atlasTextures.Length > atlasIndex ? fontAsset.atlasTextures[atlasIndex] : null;
|
||||
|
||||
if (atlasTexture == null)
|
||||
return;
|
||||
|
||||
Material mat;
|
||||
if (((GlyphRasterModes)fontAsset.atlasRenderMode & GlyphRasterModes.RASTER_MODE_BITMAP) == GlyphRasterModes.RASTER_MODE_BITMAP)
|
||||
{
|
||||
mat = TMP_FontAssetEditor.internalBitmapMaterial;
|
||||
|
||||
if (mat == null)
|
||||
return;
|
||||
|
||||
mat.mainTexture = atlasTexture;
|
||||
}
|
||||
else
|
||||
{
|
||||
mat = TMP_FontAssetEditor.internalSDFMaterial;
|
||||
|
||||
if (mat == null)
|
||||
return;
|
||||
|
||||
mat.mainTexture = atlasTexture;
|
||||
mat.SetFloat(ShaderUtilities.ID_GradientScale, fontAsset.atlasPadding + 1);
|
||||
}
|
||||
|
||||
// Draw glyph from atlas texture.
|
||||
Rect glyphDrawPosition = new Rect(position.x, position.y + 2, 64, 60);
|
||||
|
||||
GlyphRect glyphRect = glyph.glyphRect;
|
||||
|
||||
float normalizedHeight = fontAsset.faceInfo.ascentLine - fontAsset.faceInfo.descentLine;
|
||||
float scale = glyphDrawPosition.width / normalizedHeight;
|
||||
|
||||
// Compute the normalized texture coordinates
|
||||
Rect texCoords = new Rect((float)glyphRect.x / atlasTexture.width, (float)glyphRect.y / atlasTexture.height, (float)glyphRect.width / atlasTexture.width, (float)glyphRect.height / atlasTexture.height);
|
||||
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
{
|
||||
glyphDrawPosition.x += (glyphDrawPosition.width - glyphRect.width * scale) / 2;
|
||||
glyphDrawPosition.y += (glyphDrawPosition.height - glyphRect.height * scale) / 2;
|
||||
glyphDrawPosition.width = glyphRect.width * scale;
|
||||
glyphDrawPosition.height = glyphRect.height * scale;
|
||||
|
||||
// Could switch to using the default material of the font asset which would require passing scale to the shader.
|
||||
Graphics.DrawTexture(glyphDrawPosition, atlasTexture, texCoords, 0, 0, 0, 0, new Color(1f, 1f, 1f), mat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d256fa541faf5d4409992c631adb98a1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,118 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.TextCore;
|
||||
using UnityEngine.TextCore.LowLevel;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
[CustomPropertyDrawer(typeof(Glyph))]
|
||||
public class TMP_GlyphPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
SerializedProperty prop_GlyphIndex = property.FindPropertyRelative("m_Index");
|
||||
SerializedProperty prop_GlyphMetrics = property.FindPropertyRelative("m_Metrics");
|
||||
SerializedProperty prop_GlyphRect = property.FindPropertyRelative("m_GlyphRect");
|
||||
SerializedProperty prop_Scale = property.FindPropertyRelative("m_Scale");
|
||||
SerializedProperty prop_AtlasIndex = property.FindPropertyRelative("m_AtlasIndex");
|
||||
|
||||
GUIStyle style = new GUIStyle(EditorStyles.label);
|
||||
style.richText = true;
|
||||
|
||||
Rect rect = new Rect(position.x + 70, position.y, position.width, 49);
|
||||
|
||||
float labelWidth = GUI.skin.label.CalcSize(new GUIContent("ID: " + prop_GlyphIndex.intValue)).x;
|
||||
EditorGUI.LabelField(new Rect(position.x + (64 - labelWidth) / 2, position.y + 85, 64f, 18f), new GUIContent("ID: <color=#FFFF80>" + prop_GlyphIndex.intValue + "</color>"), style);
|
||||
//EditorGUIUtility.labelWidth = 22f;
|
||||
//EditorGUI.DelayedIntField(new Rect(position.x + (64 - labelWidth) / 2, position.y + 89, 58f, 18f), prop_GlyphIndex, new GUIContent("ID:"));
|
||||
|
||||
// We get Rect since a valid position may not be provided by the caller.
|
||||
EditorGUI.PropertyField(new Rect(rect.x, rect.y, position.width, 49), prop_GlyphRect);
|
||||
|
||||
rect.y += 45;
|
||||
EditorGUI.PropertyField(rect, prop_GlyphMetrics);
|
||||
|
||||
EditorGUIUtility.labelWidth = 40f;
|
||||
EditorGUI.PropertyField(new Rect(rect.x, rect.y + 65, 75, 18), prop_Scale, new GUIContent("Scale:")); // new GUIContent("Scale: <color=#FFFF80>" + prop_Scale.floatValue + "</color>"), style);
|
||||
|
||||
EditorGUIUtility.labelWidth = 74f;
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 85, rect.y + 65, 95, 18), prop_AtlasIndex, new GUIContent("Atlas Index:")); // new GUIContent("Atlas Index: <color=#FFFF80>" + prop_AtlasIndex.intValue + "</color>"), style);
|
||||
|
||||
DrawGlyph(position, property);
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return 130f;
|
||||
}
|
||||
|
||||
void DrawGlyph(Rect position, SerializedProperty property)
|
||||
{
|
||||
// Get a reference to the sprite texture
|
||||
TMP_FontAsset fontAsset = property.serializedObject.targetObject as TMP_FontAsset;
|
||||
|
||||
if (fontAsset == null)
|
||||
return;
|
||||
|
||||
// Get reference to atlas texture.
|
||||
int atlasIndex = property.FindPropertyRelative("m_AtlasIndex").intValue;
|
||||
Texture2D atlasTexture = fontAsset.atlasTextures.Length > atlasIndex ? fontAsset.atlasTextures[atlasIndex] : null;
|
||||
|
||||
if (atlasTexture == null)
|
||||
return;
|
||||
|
||||
Material mat;
|
||||
if (((GlyphRasterModes)fontAsset.atlasRenderMode & GlyphRasterModes.RASTER_MODE_BITMAP) == GlyphRasterModes.RASTER_MODE_BITMAP)
|
||||
{
|
||||
mat = TMP_FontAssetEditor.internalBitmapMaterial;
|
||||
|
||||
if (mat == null)
|
||||
return;
|
||||
|
||||
mat.mainTexture = atlasTexture;
|
||||
mat.SetColor("_Color", Color.white);
|
||||
}
|
||||
else
|
||||
{
|
||||
mat = TMP_FontAssetEditor.internalSDFMaterial;
|
||||
|
||||
if (mat == null)
|
||||
return;
|
||||
|
||||
mat.mainTexture = atlasTexture;
|
||||
mat.SetFloat(ShaderUtilities.ID_GradientScale, fontAsset.atlasPadding + 1);
|
||||
}
|
||||
|
||||
// Draw glyph from atlas texture.
|
||||
Rect glyphDrawPosition = new Rect(position.x, position.y + 2, 64, 80);
|
||||
|
||||
SerializedProperty prop_GlyphRect = property.FindPropertyRelative("m_GlyphRect");
|
||||
|
||||
int glyphOriginX = prop_GlyphRect.FindPropertyRelative("m_X").intValue;
|
||||
int glyphOriginY = prop_GlyphRect.FindPropertyRelative("m_Y").intValue;
|
||||
int glyphWidth = prop_GlyphRect.FindPropertyRelative("m_Width").intValue;
|
||||
int glyphHeight = prop_GlyphRect.FindPropertyRelative("m_Height").intValue;
|
||||
|
||||
float normalizedHeight = fontAsset.faceInfo.ascentLine - fontAsset.faceInfo.descentLine;
|
||||
float scale = glyphDrawPosition.width / normalizedHeight;
|
||||
|
||||
// Compute the normalized texture coordinates
|
||||
Rect texCoords = new Rect((float)glyphOriginX / atlasTexture.width, (float)glyphOriginY / atlasTexture.height, (float)glyphWidth / atlasTexture.width, (float)glyphHeight / atlasTexture.height);
|
||||
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
{
|
||||
glyphDrawPosition.x += (glyphDrawPosition.width - glyphWidth * scale) / 2;
|
||||
glyphDrawPosition.y += (glyphDrawPosition.height - glyphHeight * scale) / 2;
|
||||
glyphDrawPosition.width = glyphWidth * scale;
|
||||
glyphDrawPosition.height = glyphHeight * scale;
|
||||
|
||||
// Could switch to using the default material of the font asset which would require passing scale to the shader.
|
||||
Graphics.DrawTexture(glyphDrawPosition, atlasTexture, texCoords, 0, 0, 0, 0, new Color(1f, 1f, 1f), mat);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c4777500b5da6094e956c3d4f04de4db
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,283 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UI;
|
||||
using UnityEditor.AnimatedValues;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
[CanEditMultipleObjects]
|
||||
[CustomEditor(typeof(TMP_InputField), true)]
|
||||
public class TMP_InputFieldEditor : SelectableEditor
|
||||
{
|
||||
private struct m_foldout
|
||||
{ // Track Inspector foldout panel states, globally.
|
||||
public static bool textInput = true;
|
||||
public static bool fontSettings = true;
|
||||
public static bool extraSettings = true;
|
||||
//public static bool shadowSetting = false;
|
||||
//public static bool materialEditor = true;
|
||||
}
|
||||
|
||||
SerializedProperty m_TextViewport;
|
||||
SerializedProperty m_TextComponent;
|
||||
SerializedProperty m_Text;
|
||||
SerializedProperty m_ContentType;
|
||||
SerializedProperty m_LineType;
|
||||
SerializedProperty m_LineLimit;
|
||||
SerializedProperty m_InputType;
|
||||
SerializedProperty m_CharacterValidation;
|
||||
SerializedProperty m_InputValidator;
|
||||
SerializedProperty m_RegexValue;
|
||||
SerializedProperty m_KeyboardType;
|
||||
SerializedProperty m_CharacterLimit;
|
||||
SerializedProperty m_CaretBlinkRate;
|
||||
SerializedProperty m_CaretWidth;
|
||||
SerializedProperty m_CaretColor;
|
||||
SerializedProperty m_CustomCaretColor;
|
||||
SerializedProperty m_SelectionColor;
|
||||
SerializedProperty m_HideMobileKeyboard;
|
||||
SerializedProperty m_HideMobileInput;
|
||||
SerializedProperty m_Placeholder;
|
||||
SerializedProperty m_VerticalScrollbar;
|
||||
SerializedProperty m_ScrollbarScrollSensitivity;
|
||||
SerializedProperty m_OnValueChanged;
|
||||
SerializedProperty m_OnEndEdit;
|
||||
SerializedProperty m_OnSelect;
|
||||
SerializedProperty m_OnDeselect;
|
||||
SerializedProperty m_ReadOnly;
|
||||
SerializedProperty m_RichText;
|
||||
SerializedProperty m_RichTextEditingAllowed;
|
||||
SerializedProperty m_ResetOnDeActivation;
|
||||
SerializedProperty m_RestoreOriginalTextOnEscape;
|
||||
|
||||
SerializedProperty m_OnFocusSelectAll;
|
||||
SerializedProperty m_GlobalPointSize;
|
||||
SerializedProperty m_GlobalFontAsset;
|
||||
|
||||
AnimBool m_CustomColor;
|
||||
|
||||
//TMP_InputValidator m_ValidationScript;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
|
||||
m_TextViewport = serializedObject.FindProperty("m_TextViewport");
|
||||
m_TextComponent = serializedObject.FindProperty("m_TextComponent");
|
||||
m_Text = serializedObject.FindProperty("m_Text");
|
||||
m_ContentType = serializedObject.FindProperty("m_ContentType");
|
||||
m_LineType = serializedObject.FindProperty("m_LineType");
|
||||
m_LineLimit = serializedObject.FindProperty("m_LineLimit");
|
||||
m_InputType = serializedObject.FindProperty("m_InputType");
|
||||
m_CharacterValidation = serializedObject.FindProperty("m_CharacterValidation");
|
||||
m_InputValidator = serializedObject.FindProperty("m_InputValidator");
|
||||
m_RegexValue = serializedObject.FindProperty("m_RegexValue");
|
||||
m_KeyboardType = serializedObject.FindProperty("m_KeyboardType");
|
||||
m_CharacterLimit = serializedObject.FindProperty("m_CharacterLimit");
|
||||
m_CaretBlinkRate = serializedObject.FindProperty("m_CaretBlinkRate");
|
||||
m_CaretWidth = serializedObject.FindProperty("m_CaretWidth");
|
||||
m_CaretColor = serializedObject.FindProperty("m_CaretColor");
|
||||
m_CustomCaretColor = serializedObject.FindProperty("m_CustomCaretColor");
|
||||
m_SelectionColor = serializedObject.FindProperty("m_SelectionColor");
|
||||
|
||||
m_HideMobileKeyboard = serializedObject.FindProperty("m_HideSoftKeyboard");
|
||||
m_HideMobileInput = serializedObject.FindProperty("m_HideMobileInput");
|
||||
|
||||
m_Placeholder = serializedObject.FindProperty("m_Placeholder");
|
||||
m_VerticalScrollbar = serializedObject.FindProperty("m_VerticalScrollbar");
|
||||
m_ScrollbarScrollSensitivity = serializedObject.FindProperty("m_ScrollSensitivity");
|
||||
|
||||
m_OnValueChanged = serializedObject.FindProperty("m_OnValueChanged");
|
||||
m_OnEndEdit = serializedObject.FindProperty("m_OnEndEdit");
|
||||
m_OnSelect = serializedObject.FindProperty("m_OnSelect");
|
||||
m_OnDeselect = serializedObject.FindProperty("m_OnDeselect");
|
||||
m_ReadOnly = serializedObject.FindProperty("m_ReadOnly");
|
||||
m_RichText = serializedObject.FindProperty("m_RichText");
|
||||
m_RichTextEditingAllowed = serializedObject.FindProperty("m_isRichTextEditingAllowed");
|
||||
m_ResetOnDeActivation = serializedObject.FindProperty("m_ResetOnDeActivation");
|
||||
m_RestoreOriginalTextOnEscape = serializedObject.FindProperty("m_RestoreOriginalTextOnEscape");
|
||||
|
||||
m_OnFocusSelectAll = serializedObject.FindProperty("m_OnFocusSelectAll");
|
||||
m_GlobalPointSize = serializedObject.FindProperty("m_GlobalPointSize");
|
||||
m_GlobalFontAsset = serializedObject.FindProperty("m_GlobalFontAsset");
|
||||
|
||||
m_CustomColor = new AnimBool(m_CustomCaretColor.boolValue);
|
||||
m_CustomColor.valueChanged.AddListener(Repaint);
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
m_CustomColor.valueChanged.RemoveListener(Repaint);
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
base.OnInspectorGUI();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(m_TextViewport);
|
||||
|
||||
EditorGUILayout.PropertyField(m_TextComponent);
|
||||
|
||||
TextMeshProUGUI text = null;
|
||||
if (m_TextComponent != null && m_TextComponent.objectReferenceValue != null)
|
||||
{
|
||||
text = m_TextComponent.objectReferenceValue as TextMeshProUGUI;
|
||||
//if (text.supportRichText)
|
||||
//{
|
||||
// EditorGUILayout.HelpBox("Using Rich Text with input is unsupported.", MessageType.Warning);
|
||||
//}
|
||||
}
|
||||
|
||||
EditorGUI.BeginDisabledGroup(m_TextComponent == null || m_TextComponent.objectReferenceValue == null);
|
||||
|
||||
// TEXT INPUT BOX
|
||||
EditorGUILayout.PropertyField(m_Text);
|
||||
|
||||
// INPUT FIELD SETTINGS
|
||||
#region INPUT FIELD SETTINGS
|
||||
|
||||
m_foldout.fontSettings = EditorGUILayout.Foldout(m_foldout.fontSettings, "Input Field Settings", true, TMP_UIStyleManager.boldFoldout);
|
||||
|
||||
if (m_foldout.fontSettings)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(m_GlobalFontAsset, new GUIContent("Font Asset", "Set the Font Asset for both Placeholder and Input Field text object."));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
TMP_InputField inputField = target as TMP_InputField;
|
||||
inputField.SetGlobalFontAsset(m_GlobalFontAsset.objectReferenceValue as TMP_FontAsset);
|
||||
}
|
||||
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(m_GlobalPointSize, new GUIContent("Point Size", "Set the point size of both Placeholder and Input Field text object."));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
TMP_InputField inputField = target as TMP_InputField;
|
||||
inputField.SetGlobalPointSize(m_GlobalPointSize.floatValue);
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(m_CharacterLimit);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(m_ContentType);
|
||||
if (!m_ContentType.hasMultipleDifferentValues)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
if (m_ContentType.enumValueIndex == (int)TMP_InputField.ContentType.Standard ||
|
||||
m_ContentType.enumValueIndex == (int)TMP_InputField.ContentType.Autocorrected ||
|
||||
m_ContentType.enumValueIndex == (int)TMP_InputField.ContentType.Custom)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(m_LineType);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (text != null)
|
||||
{
|
||||
if (m_LineType.enumValueIndex == (int)TMP_InputField.LineType.SingleLine)
|
||||
text.enableWordWrapping = false;
|
||||
else
|
||||
{
|
||||
text.enableWordWrapping = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_LineType.enumValueIndex != (int)TMP_InputField.LineType.SingleLine)
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_LineLimit);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ContentType.enumValueIndex == (int)TMP_InputField.ContentType.Custom)
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_InputType);
|
||||
EditorGUILayout.PropertyField(m_KeyboardType);
|
||||
EditorGUILayout.PropertyField(m_CharacterValidation);
|
||||
if (m_CharacterValidation.enumValueIndex == (int)TMP_InputField.CharacterValidation.Regex)
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_RegexValue);
|
||||
}
|
||||
else if (m_CharacterValidation.enumValueIndex == (int)TMP_InputField.CharacterValidation.CustomValidator)
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_InputValidator);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(m_Placeholder);
|
||||
EditorGUILayout.PropertyField(m_VerticalScrollbar);
|
||||
|
||||
if (m_VerticalScrollbar.objectReferenceValue != null)
|
||||
EditorGUILayout.PropertyField(m_ScrollbarScrollSensitivity);
|
||||
|
||||
EditorGUILayout.PropertyField(m_CaretBlinkRate);
|
||||
EditorGUILayout.PropertyField(m_CaretWidth);
|
||||
|
||||
EditorGUILayout.PropertyField(m_CustomCaretColor);
|
||||
|
||||
m_CustomColor.target = m_CustomCaretColor.boolValue;
|
||||
|
||||
if (EditorGUILayout.BeginFadeGroup(m_CustomColor.faded))
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_CaretColor);
|
||||
}
|
||||
EditorGUILayout.EndFadeGroup();
|
||||
|
||||
EditorGUILayout.PropertyField(m_SelectionColor);
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
// CONTROL SETTINGS
|
||||
#region CONTROL SETTINGS
|
||||
m_foldout.extraSettings = EditorGUILayout.Foldout(m_foldout.extraSettings, "Control Settings", true, TMP_UIStyleManager.boldFoldout);
|
||||
|
||||
if (m_foldout.extraSettings)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
EditorGUILayout.PropertyField(m_OnFocusSelectAll, new GUIContent("OnFocus - Select All", "Should all the text be selected when the Input Field is selected."));
|
||||
EditorGUILayout.PropertyField(m_ResetOnDeActivation, new GUIContent("Reset On DeActivation", "Should the Text and Caret position be reset when Input Field is DeActivated."));
|
||||
EditorGUILayout.PropertyField(m_RestoreOriginalTextOnEscape, new GUIContent("Restore On ESC Key", "Should the original text be restored when pressing ESC."));
|
||||
EditorGUILayout.PropertyField(m_HideMobileKeyboard, new GUIContent("Hide Soft Keyboard", "Controls the visibility of the mobile virtual keyboard."));
|
||||
EditorGUILayout.PropertyField(m_HideMobileInput, new GUIContent("Hide Mobile Input", "Controls the visibility of the editable text field above the mobile virtual keyboard. Not supported on all mobile platforms."));
|
||||
EditorGUILayout.PropertyField(m_ReadOnly);
|
||||
EditorGUILayout.PropertyField(m_RichText);
|
||||
EditorGUILayout.PropertyField(m_RichTextEditingAllowed, new GUIContent("Allow Rich Text Editing"));
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(m_OnValueChanged);
|
||||
EditorGUILayout.PropertyField(m_OnEndEdit);
|
||||
EditorGUILayout.PropertyField(m_OnSelect);
|
||||
EditorGUILayout.PropertyField(m_OnDeselect);
|
||||
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa160f27c3fe4052a5850e21108811b6
|
||||
timeCreated: 1457861621
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,76 @@
|
||||
// When enabled, allows setting the material by dropping a material onto the MeshRenderer inspector component.
|
||||
// The drawback is that the MeshRenderer inspector will not have properties for light probes, so if you need light probe support, do not enable this.
|
||||
//#define ALLOW_MESHRENDERER_MATERIAL_DRAG_N_DROP
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
// Disabled for compatibility reason as lightprobe setup isn't supported due to inability to inherit from MeshRendererEditor class
|
||||
#if ALLOW_MESHRENDERER_MATERIAL_DRAG_N_DROP
|
||||
[CanEditMultipleObjects]
|
||||
[CustomEditor(typeof(MeshRenderer))]
|
||||
public class TMP_MeshRendererEditor : Editor
|
||||
{
|
||||
private SerializedProperty m_Materials;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_Materials = serializedObject.FindProperty("m_Materials");
|
||||
}
|
||||
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
// Get a reference to the current material.
|
||||
SerializedProperty material_prop = m_Materials.GetArrayElementAtIndex(0);
|
||||
Material currentMaterial = material_prop.objectReferenceValue as Material;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
base.OnInspectorGUI();
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
material_prop = m_Materials.GetArrayElementAtIndex(0);
|
||||
|
||||
TMP_FontAsset newFontAsset = null;
|
||||
Material newMaterial = null;
|
||||
|
||||
if (material_prop != null)
|
||||
newMaterial = material_prop.objectReferenceValue as Material;
|
||||
|
||||
// Check if the new material is referencing a different font atlas texture.
|
||||
if (newMaterial != null && currentMaterial.GetInstanceID() != newMaterial.GetInstanceID())
|
||||
{
|
||||
// Search for the Font Asset matching the new font atlas texture.
|
||||
newFontAsset = TMP_EditorUtility.FindMatchingFontAsset(newMaterial);
|
||||
}
|
||||
|
||||
|
||||
GameObject[] objects = Selection.gameObjects;
|
||||
|
||||
for (int i = 0; i < objects.Length; i++)
|
||||
{
|
||||
// Assign new font asset
|
||||
if (newFontAsset != null)
|
||||
{
|
||||
TMP_Text textComponent = objects[i].GetComponent<TMP_Text>();
|
||||
|
||||
if (textComponent != null)
|
||||
{
|
||||
Undo.RecordObject(textComponent, "Font Asset Change");
|
||||
textComponent.font = newFontAsset;
|
||||
}
|
||||
}
|
||||
|
||||
TMPro_EventManager.ON_DRAG_AND_DROP_MATERIAL_CHANGED(objects[i], currentMaterial, newMaterial);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d437b997e074079b4b2f6e395394f4b
|
||||
timeCreated: 1462864011
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,920 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TMPro.EditorUtilities;
|
||||
|
||||
|
||||
namespace TMPro
|
||||
{
|
||||
/// <summary>
|
||||
/// Data structure containing the target and replacement fileIDs and GUIDs which will require remapping from previous version of TextMesh Pro to the new TextMesh Pro UPM package.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
struct AssetConversionRecord
|
||||
{
|
||||
public string referencedResource;
|
||||
public string target;
|
||||
public string replacement;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Data structure containing a list of target and replacement fileID and GUID requiring remapping from previous versions of TextMesh Pro to the new TextMesh Pro UPM package.
|
||||
/// This data structure is populated with the data contained in the PackageConversionData.json file included in the package.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
class AssetConversionData
|
||||
{
|
||||
public List<AssetConversionRecord> assetRecords;
|
||||
}
|
||||
|
||||
|
||||
public class TMP_ProjectConversionUtility : EditorWindow
|
||||
{
|
||||
// Create Sprite Asset Editor Window
|
||||
[MenuItem("Window/TextMeshPro/Project Files GUID Remapping Tool", false, 2100)]
|
||||
static void ShowConverterWindow()
|
||||
{
|
||||
var window = GetWindow<TMP_ProjectConversionUtility>();
|
||||
window.titleContent = new GUIContent("Conversion Tool");
|
||||
window.Focus();
|
||||
}
|
||||
|
||||
private static HashSet<Type> m_IgnoreAssetTypes = new HashSet<Type>()
|
||||
{
|
||||
typeof(AnimatorOverrideController),
|
||||
typeof(AudioClip),
|
||||
typeof(AvatarMask),
|
||||
typeof(ComputeShader),
|
||||
typeof(Cubemap),
|
||||
typeof(DefaultAsset),
|
||||
typeof(Flare),
|
||||
typeof(Font),
|
||||
typeof(GUISkin),
|
||||
typeof(HumanTemplate),
|
||||
typeof(LightingDataAsset),
|
||||
typeof(Mesh),
|
||||
typeof(MonoScript),
|
||||
typeof(PhysicMaterial),
|
||||
typeof(PhysicsMaterial2D),
|
||||
typeof(RenderTexture),
|
||||
typeof(Shader),
|
||||
typeof(TerrainData),
|
||||
typeof(TextAsset),
|
||||
typeof(Texture2D),
|
||||
typeof(Texture2DArray),
|
||||
typeof(Texture3D),
|
||||
typeof(UnityEditor.Animations.AnimatorController),
|
||||
typeof(UnityEditorInternal.AssemblyDefinitionAsset),
|
||||
typeof(UnityEngine.AI.NavMeshData),
|
||||
typeof(UnityEngine.Tilemaps.Tile),
|
||||
typeof(UnityEngine.U2D.SpriteAtlas),
|
||||
typeof(UnityEngine.Video.VideoClip),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
struct AssetModificationRecord
|
||||
{
|
||||
public string assetFilePath;
|
||||
public string assetDataFile;
|
||||
}
|
||||
|
||||
struct AssetFileRecord
|
||||
{
|
||||
public string assetFilePath;
|
||||
public string assetMetaFilePath;
|
||||
|
||||
public AssetFileRecord(string filePath, string metaFilePath)
|
||||
{
|
||||
this.assetFilePath = filePath;
|
||||
this.assetMetaFilePath = metaFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
private static string m_ProjectPath;
|
||||
private static string m_ProjectFolderToScan;
|
||||
private static bool m_IsAlreadyScanningProject;
|
||||
private static bool m_CancelScanProcess;
|
||||
private static string k_ProjectScanReportDefaultText = "<color=#FFFF80><b>Project Scan Results</b></color>\n";
|
||||
private static string k_ProjectScanLabelPrefix = "Scanning: ";
|
||||
private static string m_ProjectScanResults = string.Empty;
|
||||
private static Vector2 m_ProjectScanResultScrollPosition;
|
||||
private static float m_ProgressPercentage = 0;
|
||||
|
||||
private static int m_ScanningTotalFiles;
|
||||
private static int m_RemainingFilesToScan;
|
||||
private static int m_ScanningCurrentFileIndex;
|
||||
private static string m_ScanningCurrentFileName;
|
||||
|
||||
private static AssetConversionData m_ConversionData;
|
||||
|
||||
private static List<AssetModificationRecord> m_ModifiedAssetList = new List<AssetModificationRecord>();
|
||||
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
// Set Editor Window Size
|
||||
SetEditorWindowSize();
|
||||
|
||||
m_ProjectScanResults = k_ProjectScanReportDefaultText;
|
||||
}
|
||||
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
GUILayout.BeginVertical();
|
||||
{
|
||||
// Scan project files and resources
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
{
|
||||
GUILayout.Label("Scan Project Files", EditorStyles.boldLabel);
|
||||
GUILayout.Label("Press the <i>Scan Project Files</i> button to begin scanning your project for files & resources that were created with a previous version of TextMesh Pro.", TMP_UIStyleManager.label);
|
||||
GUILayout.Space(10f);
|
||||
GUILayout.Label("Project folder to be scanned. Example \"Assets/TextMesh Pro\"");
|
||||
m_ProjectFolderToScan = EditorGUILayout.TextField("Folder Path: Assets/", m_ProjectFolderToScan);
|
||||
GUILayout.Space(5f);
|
||||
|
||||
GUI.enabled = m_IsAlreadyScanningProject == false ? true : false;
|
||||
if (GUILayout.Button("Scan Project Files"))
|
||||
{
|
||||
m_CancelScanProcess = false;
|
||||
|
||||
// Make sure Asset Serialization mode is set to ForceText and Version Control mode to Visible Meta Files.
|
||||
if (CheckProjectSerializationAndSourceControlModes() == true)
|
||||
{
|
||||
m_ProjectPath = Path.GetFullPath("Assets/..");
|
||||
TMP_EditorCoroutine.StartCoroutine(ScanProjectFiles());
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorUtility.DisplayDialog("Project Settings Change Required", "In menu options \"Edit - Project Settings - Editor\", please change Asset Serialization Mode to ForceText and Source Control Mode to Visible Meta Files.", "OK", string.Empty);
|
||||
}
|
||||
}
|
||||
GUI.enabled = true;
|
||||
|
||||
// Display progress bar
|
||||
Rect rect = GUILayoutUtility.GetRect(0f, 20f, GUILayout.ExpandWidth(true));
|
||||
EditorGUI.ProgressBar(rect, m_ProgressPercentage, "Scan Progress (" + m_ScanningCurrentFileIndex + "/" + m_ScanningTotalFiles + ")");
|
||||
|
||||
// Display cancel button and name of file currently being scanned.
|
||||
if (m_IsAlreadyScanningProject)
|
||||
{
|
||||
Rect cancelRect = new Rect(rect.width - 20, rect.y + 2, 20, 16);
|
||||
if (GUI.Button(cancelRect, "X"))
|
||||
{
|
||||
m_CancelScanProcess = true;
|
||||
}
|
||||
GUILayout.Label(k_ProjectScanLabelPrefix + m_ScanningCurrentFileName, TMP_UIStyleManager.label);
|
||||
}
|
||||
else
|
||||
GUILayout.Label(string.Empty);
|
||||
|
||||
GUILayout.Space(5);
|
||||
|
||||
// Creation Feedback
|
||||
GUILayout.BeginVertical(TMP_UIStyleManager.textAreaBoxWindow, GUILayout.ExpandHeight(true));
|
||||
{
|
||||
m_ProjectScanResultScrollPosition = EditorGUILayout.BeginScrollView(m_ProjectScanResultScrollPosition, GUILayout.ExpandHeight(true));
|
||||
EditorGUILayout.LabelField(m_ProjectScanResults, TMP_UIStyleManager.label);
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
GUILayout.Space(5f);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
|
||||
// Scan project files and resources
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
{
|
||||
GUILayout.Label("Save Modified Project Files", EditorStyles.boldLabel);
|
||||
GUILayout.Label("Pressing the <i>Save Modified Project Files</i> button will update the files in the <i>Project Scan Results</i> listed above. <color=#FFFF80>Please make sure that you have created a backup of your project first</color> as these file modifications are permanent and cannot be undone.", TMP_UIStyleManager.label);
|
||||
GUILayout.Space(5f);
|
||||
|
||||
GUI.enabled = m_IsAlreadyScanningProject == false && m_ModifiedAssetList.Count > 0 ? true : false;
|
||||
if (GUILayout.Button("Save Modified Project Files"))
|
||||
{
|
||||
UpdateProjectFiles();
|
||||
}
|
||||
GUILayout.Space(10f);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
GUILayout.Space(5f);
|
||||
}
|
||||
|
||||
void OnInspectorUpdate()
|
||||
{
|
||||
Repaint();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Limits the minimum size of the editor window.
|
||||
/// </summary>
|
||||
void SetEditorWindowSize()
|
||||
{
|
||||
EditorWindow editorWindow = this;
|
||||
|
||||
Vector2 currentWindowSize = editorWindow.minSize;
|
||||
|
||||
editorWindow.minSize = new Vector2(Mathf.Max(640, currentWindowSize.x), Mathf.Max(420, currentWindowSize.y));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
private static bool ShouldIgnoreFile(string filePath)
|
||||
{
|
||||
string fileExtension = Path.GetExtension(filePath);
|
||||
Type fileType = AssetDatabase.GetMainAssetTypeAtPath(filePath);
|
||||
|
||||
if (m_IgnoreAssetTypes.Contains(fileType))
|
||||
return true;
|
||||
|
||||
// Exclude FBX
|
||||
if (fileType == typeof(GameObject) && fileExtension.ToLower() == ".fbx") { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private IEnumerator ScanProjectFiles()
|
||||
{
|
||||
m_IsAlreadyScanningProject = true;
|
||||
string packageFullPath = EditorUtilities.TMP_EditorUtility.packageFullPath;
|
||||
|
||||
// List containing assets that have been modified.
|
||||
m_ProjectScanResults = k_ProjectScanReportDefaultText;
|
||||
m_ModifiedAssetList.Clear();
|
||||
m_ProgressPercentage = 0;
|
||||
|
||||
// Read Conversion Data from Json file.
|
||||
if (m_ConversionData == null)
|
||||
m_ConversionData = JsonUtility.FromJson<AssetConversionData>(File.ReadAllText(packageFullPath + "/PackageConversionData.json"));
|
||||
|
||||
// Get list of GUIDs for assets that might contain references to previous GUIDs that require updating.
|
||||
string searchFolder = string.IsNullOrEmpty(m_ProjectFolderToScan) ? "Assets" : ("Assets/" + m_ProjectFolderToScan);
|
||||
string[] guids = AssetDatabase.FindAssets("t:Object", new string[] { searchFolder }).Distinct().ToArray();
|
||||
|
||||
k_ProjectScanLabelPrefix = "<b>Phase 1 - Filtering:</b> ";
|
||||
m_ScanningTotalFiles = guids.Length;
|
||||
m_ScanningCurrentFileIndex = 0;
|
||||
|
||||
List<AssetFileRecord> projectFilesToScan = new List<AssetFileRecord>();
|
||||
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
if (m_CancelScanProcess)
|
||||
break;
|
||||
|
||||
string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
|
||||
m_ScanningCurrentFileIndex += 1;
|
||||
m_ScanningCurrentFileName = assetFilePath;
|
||||
m_ProgressPercentage = (float)m_ScanningCurrentFileIndex / m_ScanningTotalFiles;
|
||||
|
||||
// Filter out file types we have no interest in searching
|
||||
if (ShouldIgnoreFile(assetFilePath))
|
||||
continue;
|
||||
|
||||
string assetMetaFilePath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetFilePath);
|
||||
|
||||
projectFilesToScan.Add(new AssetFileRecord(assetFilePath, assetMetaFilePath));
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
m_RemainingFilesToScan = m_ScanningTotalFiles = projectFilesToScan.Count;
|
||||
|
||||
k_ProjectScanLabelPrefix = "<b>Phase 2 - Scanning:</b> ";
|
||||
|
||||
for (int i = 0; i < m_ScanningTotalFiles; i++)
|
||||
{
|
||||
if (m_CancelScanProcess)
|
||||
break;
|
||||
|
||||
AssetFileRecord fileRecord = projectFilesToScan[i];
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
ScanProjectFileAsync(fileRecord);
|
||||
|
||||
m_ScanningCurrentFileName = fileRecord.assetFilePath;
|
||||
|
||||
int completedScans = m_ScanningTotalFiles - Interlocked.Decrement(ref m_RemainingFilesToScan);
|
||||
|
||||
m_ScanningCurrentFileIndex = completedScans;
|
||||
m_ProgressPercentage = (float)completedScans / m_ScanningTotalFiles;
|
||||
});
|
||||
|
||||
if (i % 64 == 0)
|
||||
yield return new WaitForSeconds(2.0f);
|
||||
|
||||
}
|
||||
|
||||
while (m_RemainingFilesToScan > 0 && !m_CancelScanProcess)
|
||||
yield return null;
|
||||
|
||||
m_IsAlreadyScanningProject = false;
|
||||
m_ScanningCurrentFileName = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
static void ScanProjectFileAsync(AssetFileRecord fileRecord)
|
||||
{
|
||||
if (m_CancelScanProcess)
|
||||
return;
|
||||
|
||||
// Read the asset data file
|
||||
string assetDataFile = string.Empty;
|
||||
bool hasFileChanged = false;
|
||||
|
||||
try
|
||||
{
|
||||
assetDataFile = File.ReadAllText(m_ProjectPath + "/" + fileRecord.assetFilePath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Continue to the next asset if we can't read the current one.
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the asset meta data file
|
||||
string assetMetaFile = File.ReadAllText(m_ProjectPath + "/" + fileRecord.assetMetaFilePath);
|
||||
bool hasMetaFileChanges = false;
|
||||
|
||||
foreach (AssetConversionRecord record in m_ConversionData.assetRecords)
|
||||
{
|
||||
if (assetDataFile.Contains(record.target))
|
||||
{
|
||||
hasFileChanged = true;
|
||||
|
||||
assetDataFile = assetDataFile.Replace(record.target, record.replacement);
|
||||
}
|
||||
|
||||
//// Check meta file
|
||||
if (assetMetaFile.Contains(record.target))
|
||||
{
|
||||
hasMetaFileChanges = true;
|
||||
|
||||
assetMetaFile = assetMetaFile.Replace(record.target, record.replacement);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasFileChanged)
|
||||
{
|
||||
AssetModificationRecord modifiedAsset;
|
||||
modifiedAsset.assetFilePath = fileRecord.assetFilePath;
|
||||
modifiedAsset.assetDataFile = assetDataFile;
|
||||
|
||||
m_ModifiedAssetList.Add(modifiedAsset);
|
||||
|
||||
m_ProjectScanResults += fileRecord.assetFilePath + "\n";
|
||||
}
|
||||
|
||||
if (hasMetaFileChanges)
|
||||
{
|
||||
AssetModificationRecord modifiedAsset;
|
||||
modifiedAsset.assetFilePath = fileRecord.assetMetaFilePath;
|
||||
modifiedAsset.assetDataFile = assetMetaFile;
|
||||
|
||||
m_ModifiedAssetList.Add(modifiedAsset);
|
||||
|
||||
m_ProjectScanResults += fileRecord.assetMetaFilePath + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private static void ResetScanProcess()
|
||||
{
|
||||
m_IsAlreadyScanningProject = false;
|
||||
m_ScanningCurrentFileName = string.Empty;
|
||||
m_ProgressPercentage = 0;
|
||||
m_ScanningCurrentFileIndex = 0;
|
||||
m_ScanningTotalFiles = 0;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private static void UpdateProjectFiles()
|
||||
{
|
||||
// Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
|
||||
CheckProjectSerializationAndSourceControlModes();
|
||||
|
||||
string projectPath = Path.GetFullPath("Assets/..");
|
||||
|
||||
// Display dialogue to show user a list of project files that will be modified upon their consent.
|
||||
if (EditorUtility.DisplayDialog("Save Modified Asset(s)?", "Are you sure you want to save all modified assets?", "YES", "NO"))
|
||||
{
|
||||
for (int i = 0; i < m_ModifiedAssetList.Count; i++)
|
||||
{
|
||||
// Make sure all file streams that might have been opened by Unity are closed.
|
||||
//AssetDatabase.ReleaseCachedFileHandles();
|
||||
|
||||
//Debug.Log("Writing asset file [" + m_ModifiedAssetList[i].assetFilePath + "].");
|
||||
|
||||
File.WriteAllText(projectPath + "/" + m_ModifiedAssetList[i].assetFilePath, m_ModifiedAssetList[i].assetDataFile);
|
||||
}
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
m_ProgressPercentage = 0;
|
||||
m_ProjectScanResults = k_ProjectScanReportDefaultText;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Check project Asset Serialization and Source Control modes
|
||||
/// </summary>
|
||||
private static bool CheckProjectSerializationAndSourceControlModes()
|
||||
{
|
||||
// Check Project Asset Serialization and Visible Meta Files mode.
|
||||
if (EditorSettings.serializationMode != SerializationMode.ForceText || EditorSettings.externalVersionControl != "Visible Meta Files")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class TMP_PackageUtilities : Editor
|
||||
{
|
||||
|
||||
enum SaveAssetDialogueOptions { Unset = 0, Save = 1, SaveAll = 2, DoNotSave = 3 };
|
||||
|
||||
private static SerializationMode m_ProjectAssetSerializationMode;
|
||||
private static string m_ProjectExternalVersionControl;
|
||||
|
||||
struct AssetRemappingRecord
|
||||
{
|
||||
public string oldGuid;
|
||||
public string newGuid;
|
||||
public string assetPath;
|
||||
}
|
||||
|
||||
struct AssetModificationRecord
|
||||
{
|
||||
public string assetFilePath;
|
||||
public string assetDataFile;
|
||||
}
|
||||
|
||||
// Create Sprite Asset Editor Window
|
||||
//[MenuItem("Window/TextMeshPro/Generate New Package GUIDs", false, 1500)]
|
||||
public static void GenerateNewPackageGUIDs_Menu()
|
||||
{
|
||||
GenerateNewPackageGUIDs();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[MenuItem("Window/TextMeshPro/Import TMP Essential Resources", false, 2050)]
|
||||
public static void ImportProjectResourcesMenu()
|
||||
{
|
||||
ImportProjectResources();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[MenuItem("Window/TextMeshPro/Import TMP Examples and Extras", false, 2051)]
|
||||
public static void ImportExamplesContentMenu()
|
||||
{
|
||||
ImportExtraContent();
|
||||
}
|
||||
|
||||
|
||||
// Create Sprite Asset Editor Window
|
||||
//[MenuItem("Window/TextMeshPro/Convert TMP Project Files to UPM", false, 1510)]
|
||||
public static void ConvertProjectGUIDsMenu()
|
||||
{
|
||||
ConvertProjectGUIDsToUPM();
|
||||
|
||||
//GetVersionInfo();
|
||||
}
|
||||
|
||||
|
||||
// Create Sprite Asset Editor Window
|
||||
//[MenuItem("Window/TextMeshPro/Convert GUID (Source to DLL)", false, 2010)]
|
||||
public static void ConvertGUIDFromSourceToDLLMenu()
|
||||
{
|
||||
//ConvertGUIDFromSourceToDLL();
|
||||
|
||||
//GetVersionInfo();
|
||||
}
|
||||
|
||||
|
||||
// Create Sprite Asset Editor Window
|
||||
//[MenuItem("Window/TextMeshPro/Convert GUID (DLL to Source)", false, 2020)]
|
||||
public static void ConvertGUIDFromDllToSourceMenu()
|
||||
{
|
||||
//ConvertGUIDFromDLLToSource();
|
||||
|
||||
//GetVersionInfo();
|
||||
}
|
||||
|
||||
|
||||
// Create Sprite Asset Editor Window
|
||||
//[MenuItem("Window/TextMeshPro/Extract Package GUIDs", false, 1530)]
|
||||
public static void ExtractPackageGUIDMenu()
|
||||
{
|
||||
ExtractPackageGUIDs();
|
||||
}
|
||||
|
||||
|
||||
private static void GetVersionInfo()
|
||||
{
|
||||
string version = TMP_Settings.version;
|
||||
Debug.Log("The version of this TextMesh Pro UPM package is (" + version + ").");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private static void ImportExtraContent()
|
||||
{
|
||||
string packageFullPath = EditorUtilities.TMP_EditorUtility.packageFullPath;
|
||||
|
||||
AssetDatabase.ImportPackage(packageFullPath + "/Package Resources/TMP Examples & Extras.unitypackage", true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private static void ImportProjectResources()
|
||||
{
|
||||
string packageFullPath = EditorUtilities.TMP_EditorUtility.packageFullPath;
|
||||
|
||||
AssetDatabase.ImportPackage(packageFullPath + "/Package Resources/TMP Essential Resources.unitypackage", true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private static void GenerateNewPackageGUIDs()
|
||||
{
|
||||
// Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
|
||||
SetProjectSerializationAndSourceControlModes();
|
||||
|
||||
string projectPath = Path.GetFullPath("Assets/..");
|
||||
|
||||
// Clear existing dictionary of AssetRecords
|
||||
List<AssetRemappingRecord> assetRecords = new List<AssetRemappingRecord>();
|
||||
|
||||
// Get full list of GUIDs used in the package which including folders.
|
||||
string[] packageGUIDs = AssetDatabase.FindAssets("t:Object", new string[] { "Assets/Packages/com.unity.TextMeshPro" });
|
||||
|
||||
for (int i = 0; i < packageGUIDs.Length; i++)
|
||||
{
|
||||
// Could add a progress bar for this process (if needed)
|
||||
|
||||
string guid = packageGUIDs[i];
|
||||
string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
string assetMetaFilePath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetFilePath);
|
||||
//System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetFilePath);
|
||||
|
||||
AssetRemappingRecord assetRecord;
|
||||
assetRecord.oldGuid = guid;
|
||||
assetRecord.assetPath = assetFilePath;
|
||||
|
||||
string newGUID = GenerateUniqueGUID();
|
||||
|
||||
assetRecord.newGuid = newGUID;
|
||||
|
||||
if (assetRecords.FindIndex(item => item.oldGuid == guid) != -1)
|
||||
continue;
|
||||
|
||||
assetRecords.Add(assetRecord);
|
||||
|
||||
// Read the meta file for the given asset.
|
||||
string assetMetaFile = File.ReadAllText(projectPath + "/" + assetMetaFilePath);
|
||||
|
||||
assetMetaFile = assetMetaFile.Replace("guid: " + guid, "guid: " + newGUID);
|
||||
|
||||
File.WriteAllText(projectPath + "/" + assetMetaFilePath, assetMetaFile);
|
||||
|
||||
//Debug.Log("Asset: [" + assetFilePath + "] Type: " + assetType + " Current GUID: [" + guid + "] New GUID: [" + newGUID + "]");
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
// Get list of GUIDs for assets that might need references to previous GUIDs which need to be updated.
|
||||
packageGUIDs = AssetDatabase.FindAssets("t:Object"); // ("t:Object", new string[] { "Assets/Asset Importer" });
|
||||
|
||||
for (int i = 0; i < packageGUIDs.Length; i++)
|
||||
{
|
||||
// Could add a progress bar for this process
|
||||
|
||||
string guid = packageGUIDs[i];
|
||||
string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetFilePath);
|
||||
|
||||
// Filter out file types we are not interested in
|
||||
if (assetType == typeof(DefaultAsset) || assetType == typeof(MonoScript) || assetType == typeof(Texture2D) || assetType == typeof(TextAsset) || assetType == typeof(Shader))
|
||||
continue;
|
||||
|
||||
// Read the asset data file
|
||||
string assetDataFile = File.ReadAllText(projectPath + "/" + assetFilePath);
|
||||
|
||||
//Debug.Log("Searching Asset: [" + assetFilePath + "] of type: " + assetType);
|
||||
|
||||
bool hasFileChanged = false;
|
||||
|
||||
foreach (AssetRemappingRecord record in assetRecords)
|
||||
{
|
||||
if (assetDataFile.Contains(record.oldGuid))
|
||||
{
|
||||
hasFileChanged = true;
|
||||
|
||||
assetDataFile = assetDataFile.Replace(record.oldGuid, record.newGuid);
|
||||
|
||||
Debug.Log("Replacing old GUID: [" + record.oldGuid + "] by new GUID: [" + record.newGuid + "] in asset file: [" + assetFilePath + "].");
|
||||
}
|
||||
}
|
||||
|
||||
if (hasFileChanged)
|
||||
{
|
||||
// Add file to list of changed files
|
||||
File.WriteAllText(projectPath + "/" + assetFilePath, assetDataFile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
// Restore project Asset Serialization and Source Control modes.
|
||||
RestoreProjectSerializationAndSourceControlModes();
|
||||
}
|
||||
|
||||
|
||||
private static void ExtractPackageGUIDs()
|
||||
{
|
||||
// Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
|
||||
SetProjectSerializationAndSourceControlModes();
|
||||
|
||||
string projectPath = Path.GetFullPath("Assets/..");
|
||||
|
||||
// Create new instance of AssetConversionData file
|
||||
AssetConversionData data = new AssetConversionData();
|
||||
data.assetRecords = new List<AssetConversionRecord>();
|
||||
|
||||
// Get full list of GUIDs used in the package which including folders.
|
||||
string[] packageGUIDs = AssetDatabase.FindAssets("t:Object", new string[] { "Assets/Packages/com.unity.TextMeshPro" });
|
||||
|
||||
for (int i = 0; i < packageGUIDs.Length; i++)
|
||||
{
|
||||
// Could add a progress bar for this process (if needed)
|
||||
|
||||
string guid = packageGUIDs[i];
|
||||
string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
//string assetMetaFilePath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetFilePath);
|
||||
|
||||
//ObjectIdentifier[] localIdentifider = BundleBuildInterface.GetPlayerObjectIdentifiersInAsset(new GUID(guid), BuildTarget.NoTarget);
|
||||
//System.Type[] types = BundleBuildInterface.GetTypeForObjects(localIdentifider);
|
||||
|
||||
System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetFilePath);
|
||||
|
||||
// Filter out file types we are not interested in
|
||||
if (assetType == typeof(DefaultAsset))
|
||||
continue;
|
||||
|
||||
string newGuid = GenerateUniqueGUID();
|
||||
|
||||
AssetConversionRecord record;
|
||||
record.referencedResource = Path.GetFileName(assetFilePath);
|
||||
record.target = "fileID: 2108210716, guid: " + newGuid;
|
||||
|
||||
record.replacement = "fileID: 11500000, guid: " + guid;
|
||||
|
||||
//if (m_AssetRecords.FindIndex(item => item.oldGuid == guid) != -1)
|
||||
// continue;
|
||||
|
||||
data.assetRecords.Add(record);
|
||||
|
||||
// Read the meta file for the given asset.
|
||||
//string assetMetaFile = File.ReadAllText(projectPath + "/" + assetMetaFilePath);
|
||||
|
||||
//assetMetaFile = assetMetaFile.Replace("guid: " + guid, "guid: " + newGUID);
|
||||
|
||||
//File.WriteAllText(projectPath + "/" + assetMetaFilePath, assetMetaFile);
|
||||
|
||||
Debug.Log("Asset: [" + Path.GetFileName(assetFilePath) + "] Type: " + assetType + " Current GUID: [" + guid + "] New GUID: [" + newGuid + "]");
|
||||
}
|
||||
|
||||
// Write new information into JSON file
|
||||
string dataFile = JsonUtility.ToJson(data, true);
|
||||
|
||||
File.WriteAllText(projectPath + "/Assets/Packages/com.unity.TextMeshPro/PackageConversionData.json", dataFile);
|
||||
|
||||
// Restore project Asset Serialization and Source Control modes.
|
||||
RestoreProjectSerializationAndSourceControlModes();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private static void ConvertProjectGUIDsToUPM()
|
||||
{
|
||||
// Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
|
||||
SetProjectSerializationAndSourceControlModes();
|
||||
|
||||
string projectPath = Path.GetFullPath("Assets/..");
|
||||
string packageFullPath = EditorUtilities.TMP_EditorUtility.packageFullPath;
|
||||
|
||||
// List containing assets that have been modified.
|
||||
List<AssetModificationRecord> modifiedAssetList = new List<AssetModificationRecord>();
|
||||
|
||||
// Read Conversion Data from Json file.
|
||||
AssetConversionData conversionData = JsonUtility.FromJson<AssetConversionData>(File.ReadAllText(packageFullPath + "/PackageConversionData.json"));
|
||||
|
||||
// Get list of GUIDs for assets that might contain references to previous GUIDs that require updating.
|
||||
string[] projectGUIDs = AssetDatabase.FindAssets("t:Object");
|
||||
|
||||
for (int i = 0; i < projectGUIDs.Length; i++)
|
||||
{
|
||||
// Could add a progress bar for this process
|
||||
|
||||
string guid = projectGUIDs[i];
|
||||
string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetFilePath);
|
||||
|
||||
// Filter out file types we are not interested in
|
||||
if (assetType == typeof(DefaultAsset) || assetType == typeof(MonoScript) || assetType == typeof(Texture2D) || assetType == typeof(TextAsset) || assetType == typeof(Shader))
|
||||
continue;
|
||||
|
||||
// Read the asset data file
|
||||
string assetDataFile = File.ReadAllText(projectPath + "/" + assetFilePath);
|
||||
|
||||
//Debug.Log("Searching Asset: [" + assetFilePath + "] of type: " + assetType);
|
||||
|
||||
bool hasFileChanged = false;
|
||||
|
||||
foreach (AssetConversionRecord record in conversionData.assetRecords)
|
||||
{
|
||||
if (assetDataFile.Contains(record.target))
|
||||
{
|
||||
hasFileChanged = true;
|
||||
|
||||
assetDataFile = assetDataFile.Replace(record.target, record.replacement);
|
||||
|
||||
Debug.Log("Replacing Reference to [" + record.referencedResource + "] using [" + record.target + "] with [" + record.replacement + "] in asset file: [" + assetFilePath + "].");
|
||||
}
|
||||
}
|
||||
|
||||
if (hasFileChanged)
|
||||
{
|
||||
Debug.Log("Adding [" + assetFilePath + "] to list of assets to be modified.");
|
||||
|
||||
AssetModificationRecord modifiedAsset;
|
||||
modifiedAsset.assetFilePath = assetFilePath;
|
||||
modifiedAsset.assetDataFile = assetDataFile;
|
||||
|
||||
modifiedAssetList.Add(modifiedAsset);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Scan project meta files to update GUIDs of assets whose GUID has changed.
|
||||
projectGUIDs = AssetDatabase.FindAssets("t:Object");
|
||||
|
||||
for (int i = 0; i < projectGUIDs.Length; i++)
|
||||
{
|
||||
string guid = projectGUIDs[i];
|
||||
string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
string assetMetaFilePath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetFilePath);
|
||||
|
||||
// Read the asset meta data file
|
||||
string assetMetaFile = File.ReadAllText(projectPath + "/" + assetMetaFilePath);
|
||||
|
||||
bool hasFileChanged = false;
|
||||
|
||||
foreach (AssetConversionRecord record in conversionData.assetRecords)
|
||||
{
|
||||
if (assetMetaFile.Contains(record.target))
|
||||
{
|
||||
hasFileChanged = true;
|
||||
|
||||
assetMetaFile = assetMetaFile.Replace(record.target, record.replacement);
|
||||
|
||||
Debug.Log("Replacing Reference to [" + record.referencedResource + "] using [" + record.target + "] with [" + record.replacement + "] in asset file: [" + assetMetaFilePath + "].");
|
||||
}
|
||||
}
|
||||
|
||||
if (hasFileChanged)
|
||||
{
|
||||
Debug.Log("Adding [" + assetMetaFilePath + "] to list of meta files to be modified.");
|
||||
|
||||
AssetModificationRecord modifiedAsset;
|
||||
modifiedAsset.assetFilePath = assetMetaFilePath;
|
||||
modifiedAsset.assetDataFile = assetMetaFile;
|
||||
|
||||
modifiedAssetList.Add(modifiedAsset);
|
||||
}
|
||||
}
|
||||
|
||||
// Display dialogue to show user a list of project files that will be modified upon their consent.
|
||||
if (EditorUtility.DisplayDialog("Save Modified Asset(s)?", "Are you sure you want to save all modified assets?", "YES", "NO"))
|
||||
{
|
||||
for (int i = 0; i < modifiedAssetList.Count; i++)
|
||||
{
|
||||
// Make sure all file streams that might have been opened by Unity are closed.
|
||||
//AssetDatabase.ReleaseCachedFileHandles();
|
||||
|
||||
Debug.Log("Writing asset file [" + modifiedAssetList[i].assetFilePath + "].");
|
||||
|
||||
//File.WriteAllText(projectPath + "/" + modifiedAssetList[i].assetFilePath, modifiedAssetList[i].assetDataFile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
// Restore project Asset Serialization and Source Control modes.
|
||||
RestoreProjectSerializationAndSourceControlModes();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static string GenerateUniqueGUID()
|
||||
{
|
||||
string monoGuid = System.Guid.NewGuid().ToString();
|
||||
|
||||
char[] charGuid = new char[32];
|
||||
int index = 0;
|
||||
for (int i = 0; i < monoGuid.Length; i++)
|
||||
{
|
||||
if (monoGuid[i] != '-')
|
||||
charGuid[index++] = monoGuid[i];
|
||||
}
|
||||
|
||||
string guid = new string(charGuid);
|
||||
|
||||
// Make sure new GUID is not already used by some other asset.
|
||||
if (AssetDatabase.GUIDToAssetPath(guid) != string.Empty)
|
||||
guid = GenerateUniqueGUID();
|
||||
|
||||
return guid;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Change project asset serialization mode to ForceText (if necessary)
|
||||
/// </summary>
|
||||
private static void SetProjectSerializationAndSourceControlModes()
|
||||
{
|
||||
// Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
|
||||
m_ProjectAssetSerializationMode = EditorSettings.serializationMode;
|
||||
if (m_ProjectAssetSerializationMode != SerializationMode.ForceText)
|
||||
UnityEditor.EditorSettings.serializationMode = SerializationMode.ForceText;
|
||||
|
||||
m_ProjectExternalVersionControl = EditorSettings.externalVersionControl;
|
||||
if (m_ProjectExternalVersionControl != "Visible Meta Files")
|
||||
UnityEditor.EditorSettings.externalVersionControl = "Visible Meta Files";
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Revert potential change to asset serialization mode (if necessary)
|
||||
/// </summary>
|
||||
private static void RestoreProjectSerializationAndSourceControlModes()
|
||||
{
|
||||
// Make sure Asset Serialization mode is set to ForceText with Visible Meta Files.
|
||||
if (m_ProjectAssetSerializationMode != EditorSettings.serializationMode)
|
||||
EditorSettings.serializationMode = m_ProjectAssetSerializationMode;
|
||||
|
||||
if (m_ProjectExternalVersionControl != EditorSettings.externalVersionControl)
|
||||
EditorSettings.externalVersionControl = m_ProjectExternalVersionControl;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68eedd4e5b33b37429c02c4add0036fe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,63 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Callbacks;
|
||||
using System.IO;
|
||||
|
||||
|
||||
namespace TMPro
|
||||
{
|
||||
public class TMP_PostBuildProcessHandler
|
||||
{
|
||||
[PostProcessBuildAttribute(10000)]
|
||||
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
|
||||
{
|
||||
// Check if TMP Essential Resource are present in user project.
|
||||
if (target == BuildTarget.iOS && File.Exists(GetEssentialProjectResourcesPath() + "/Resources/TMP Settings.asset") && TMP_Settings.enableEmojiSupport)
|
||||
{
|
||||
string file = Path.Combine(pathToBuiltProject, "Classes/UI/Keyboard.mm");
|
||||
string content = File.ReadAllText(file);
|
||||
content = content.Replace("FILTER_EMOJIS_IOS_KEYBOARD 1", "FILTER_EMOJIS_IOS_KEYBOARD 0");
|
||||
File.WriteAllText(file, content);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static string GetEssentialProjectResourcesPath()
|
||||
{
|
||||
// Find the potential location of the TextMesh Pro folder in the user project.
|
||||
string projectPath = Path.GetFullPath("Assets/..");
|
||||
if (Directory.Exists(projectPath))
|
||||
{
|
||||
// Search for default location of TMP Essential Resources
|
||||
if (Directory.Exists(projectPath + "/Assets/TextMesh Pro/Resources"))
|
||||
{
|
||||
return "Assets/TextMesh Pro";
|
||||
}
|
||||
|
||||
// Search for potential alternative locations in the user project
|
||||
string[] matchingPaths = Directory.GetDirectories(projectPath, "TextMesh Pro", SearchOption.AllDirectories);
|
||||
projectPath = ValidateLocation(matchingPaths, projectPath);
|
||||
if (projectPath != null) return projectPath;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static string ValidateLocation(string[] paths, string projectPath)
|
||||
{
|
||||
for (int i = 0; i < paths.Length; i++)
|
||||
{
|
||||
// Check if any of the matching directories contain a GUISkins directory.
|
||||
if (Directory.Exists(paths[i] + "/Resources"))
|
||||
{
|
||||
string folderPath = paths[i].Replace(projectPath, "");
|
||||
folderPath = folderPath.TrimStart('\\', '/');
|
||||
return folderPath;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fdea2af3daa40fe8f88e5e9cfc17abb
|
||||
timeCreated: 1479886230
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,43 @@
|
||||
#if !UNITY_2018_3_OR_NEWER
|
||||
using UnityEditor;
|
||||
|
||||
namespace TMPro
|
||||
{
|
||||
|
||||
public static class TMP_ProjectTextSettings
|
||||
{
|
||||
// Open Project Text Settings
|
||||
[MenuItem("Edit/Project Settings/TextMeshPro Settings", false, 309)]
|
||||
public static void SelectProjectTextSettings()
|
||||
{
|
||||
TMP_Settings textSettings = TMP_Settings.instance;
|
||||
|
||||
if (textSettings)
|
||||
{
|
||||
Selection.activeObject = textSettings;
|
||||
|
||||
// TODO: Do we want to ping the Project Text Settings asset in the Project Inspector
|
||||
EditorUtility.FocusProjectWindow();
|
||||
EditorGUIUtility.PingObject(textSettings);
|
||||
}
|
||||
else
|
||||
TMPro_EventManager.RESOURCE_LOAD_EVENT.Add(ON_RESOURCES_LOADED);
|
||||
}
|
||||
|
||||
|
||||
// Event received when TMP resources have been loaded.
|
||||
static void ON_RESOURCES_LOADED()
|
||||
{
|
||||
TMPro_EventManager.RESOURCE_LOAD_EVENT.Remove(ON_RESOURCES_LOADED);
|
||||
|
||||
TMP_Settings textSettings = TMP_Settings.instance;
|
||||
|
||||
Selection.activeObject = textSettings;
|
||||
|
||||
// TODO: Do we want to ping the Project Text Settings asset in the Project Inspector
|
||||
EditorUtility.FocusProjectWindow();
|
||||
EditorGUIUtility.PingObject(textSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e751e877ed14d71a6b8e63ac54949cf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,68 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
//[InitializeOnLoad]
|
||||
class TMP_ResourcesLoader
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Function to pre-load the TMP Resources
|
||||
/// </summary>
|
||||
public static void LoadTextMeshProResources()
|
||||
{
|
||||
//TMP_Settings.LoadDefaultSettings();
|
||||
//TMP_StyleSheet.LoadDefaultStyleSheet();
|
||||
}
|
||||
|
||||
|
||||
static TMP_ResourcesLoader()
|
||||
{
|
||||
//Debug.Log("Loading TMP Resources...");
|
||||
|
||||
// Get current targetted platform
|
||||
|
||||
|
||||
//string Settings = PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone);
|
||||
//TMPro.TMP_Settings.LoadDefaultSettings();
|
||||
//TMPro.TMP_StyleSheet.LoadDefaultStyleSheet();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
//static void OnBeforeSceneLoaded()
|
||||
//{
|
||||
//Debug.Log("Before scene is loaded.");
|
||||
|
||||
// //TMPro.TMP_Settings.LoadDefaultSettings();
|
||||
// //TMPro.TMP_StyleSheet.LoadDefaultStyleSheet();
|
||||
|
||||
// //ShaderVariantCollection collection = new ShaderVariantCollection();
|
||||
// //Shader s0 = Shader.Find("TextMeshPro/Mobile/Distance Field");
|
||||
// //ShaderVariantCollection.ShaderVariant tmp_Variant = new ShaderVariantCollection.ShaderVariant(s0, UnityEngine.Rendering.PassType.Normal, string.Empty);
|
||||
|
||||
// //collection.Add(tmp_Variant);
|
||||
// //collection.WarmUp();
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
//static class TMP_ProjectSettings
|
||||
//{
|
||||
// [InitializeOnLoadMethod]
|
||||
// static void SetProjectDefineSymbols()
|
||||
// {
|
||||
// string currentBuildSettings = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
|
||||
|
||||
// //Check for and inject TMP_INSTALLED
|
||||
// if (!currentBuildSettings.Contains("TMP_PRESENT"))
|
||||
// {
|
||||
// PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, currentBuildSettings + ";TMP_PRESENT");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7241c7dc25374fc1a6ab3ef9da79c363
|
||||
timeCreated: 1465441092
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,442 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
public class TMP_SDFShaderGUI : TMP_BaseShaderGUI
|
||||
{
|
||||
static ShaderFeature s_OutlineFeature, s_UnderlayFeature, s_BevelFeature, s_GlowFeature, s_MaskFeature;
|
||||
|
||||
static bool s_Face = true, s_Outline = true, s_Underlay, s_Lighting, s_Glow, s_Bevel, s_Light, s_Bump, s_Env;
|
||||
|
||||
static string[]
|
||||
s_FaceUvSpeedNames = { "_FaceUVSpeedX", "_FaceUVSpeedY" },
|
||||
s_OutlineUvSpeedNames = { "_OutlineUVSpeedX", "_OutlineUVSpeedY" };
|
||||
|
||||
static TMP_SDFShaderGUI()
|
||||
{
|
||||
s_OutlineFeature = new ShaderFeature()
|
||||
{
|
||||
undoLabel = "Outline",
|
||||
keywords = new[] { "OUTLINE_ON" }
|
||||
};
|
||||
|
||||
s_UnderlayFeature = new ShaderFeature()
|
||||
{
|
||||
undoLabel = "Underlay",
|
||||
keywords = new[] { "UNDERLAY_ON", "UNDERLAY_INNER" },
|
||||
label = new GUIContent("Underlay Type"),
|
||||
keywordLabels = new[]
|
||||
{
|
||||
new GUIContent("None"), new GUIContent("Normal"), new GUIContent("Inner")
|
||||
}
|
||||
};
|
||||
|
||||
s_BevelFeature = new ShaderFeature()
|
||||
{
|
||||
undoLabel = "Bevel",
|
||||
keywords = new[] { "BEVEL_ON" }
|
||||
};
|
||||
|
||||
s_GlowFeature = new ShaderFeature()
|
||||
{
|
||||
undoLabel = "Glow",
|
||||
keywords = new[] { "GLOW_ON" }
|
||||
};
|
||||
|
||||
s_MaskFeature = new ShaderFeature()
|
||||
{
|
||||
undoLabel = "Mask",
|
||||
keywords = new[] { "MASK_HARD", "MASK_SOFT" },
|
||||
label = new GUIContent("Mask"),
|
||||
keywordLabels = new[]
|
||||
{
|
||||
new GUIContent("Mask Off"), new GUIContent("Mask Hard"), new GUIContent("Mask Soft")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void DoGUI()
|
||||
{
|
||||
s_Face = BeginPanel("Face", s_Face);
|
||||
if (s_Face)
|
||||
{
|
||||
DoFacePanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
|
||||
s_Outline = m_Material.HasProperty(ShaderUtilities.ID_OutlineTex) ? BeginPanel("Outline", s_Outline) : BeginPanel("Outline", s_OutlineFeature, s_Outline);
|
||||
if (s_Outline)
|
||||
{
|
||||
DoOutlinePanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
|
||||
if (m_Material.HasProperty(ShaderUtilities.ID_UnderlayColor))
|
||||
{
|
||||
s_Underlay = BeginPanel("Underlay", s_UnderlayFeature, s_Underlay);
|
||||
if (s_Underlay)
|
||||
{
|
||||
DoUnderlayPanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
}
|
||||
|
||||
if (m_Material.HasProperty("_SpecularColor"))
|
||||
{
|
||||
s_Lighting = BeginPanel("Lighting", s_BevelFeature, s_Lighting);
|
||||
if (s_Lighting)
|
||||
{
|
||||
s_Bevel = BeginPanel("Bevel", s_Bevel);
|
||||
if (s_Bevel)
|
||||
{
|
||||
DoBevelPanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
|
||||
s_Light = BeginPanel("Local Lighting", s_Light);
|
||||
if (s_Light)
|
||||
{
|
||||
DoLocalLightingPanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
|
||||
s_Bump = BeginPanel("Bump Map", s_Bump);
|
||||
if (s_Bump)
|
||||
{
|
||||
DoBumpMapPanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
|
||||
s_Env = BeginPanel("Environment Map", s_Env);
|
||||
if (s_Env)
|
||||
{
|
||||
DoEnvMapPanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
}
|
||||
else if (m_Material.HasProperty("_SpecColor"))
|
||||
{
|
||||
s_Bevel = BeginPanel("Bevel", s_Bevel);
|
||||
if (s_Bevel)
|
||||
{
|
||||
DoBevelPanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
|
||||
s_Light = BeginPanel("Surface Lighting", s_Light);
|
||||
if (s_Light)
|
||||
{
|
||||
DoSurfaceLightingPanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
|
||||
s_Bump = BeginPanel("Bump Map", s_Bump);
|
||||
if (s_Bump)
|
||||
{
|
||||
DoBumpMapPanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
|
||||
s_Env = BeginPanel("Environment Map", s_Env);
|
||||
if (s_Env)
|
||||
{
|
||||
DoEnvMapPanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
}
|
||||
|
||||
if (m_Material.HasProperty(ShaderUtilities.ID_GlowColor))
|
||||
{
|
||||
s_Glow = BeginPanel("Glow", s_GlowFeature, s_Glow);
|
||||
if (s_Glow)
|
||||
{
|
||||
DoGlowPanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
}
|
||||
|
||||
s_DebugExtended = BeginPanel("Debug Settings", s_DebugExtended);
|
||||
if (s_DebugExtended)
|
||||
{
|
||||
DoDebugPanel();
|
||||
}
|
||||
|
||||
EndPanel();
|
||||
}
|
||||
|
||||
void DoFacePanel()
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
DoColor("_FaceColor", "Color");
|
||||
if (m_Material.HasProperty(ShaderUtilities.ID_FaceTex))
|
||||
{
|
||||
if (m_Material.HasProperty("_FaceUVSpeedX"))
|
||||
{
|
||||
DoTexture2D("_FaceTex", "Texture", true, s_FaceUvSpeedNames);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoTexture2D("_FaceTex", "Texture", true);
|
||||
}
|
||||
}
|
||||
|
||||
DoSlider("_OutlineSoftness", "Softness");
|
||||
DoSlider("_FaceDilate", "Dilate");
|
||||
if (m_Material.HasProperty(ShaderUtilities.ID_Shininess))
|
||||
{
|
||||
DoSlider("_FaceShininess", "Gloss");
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel -= 1;
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
void DoOutlinePanel()
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
DoColor("_OutlineColor", "Color");
|
||||
if (m_Material.HasProperty(ShaderUtilities.ID_OutlineTex))
|
||||
{
|
||||
if (m_Material.HasProperty("_OutlineUVSpeedX"))
|
||||
{
|
||||
DoTexture2D("_OutlineTex", "Texture", true, s_OutlineUvSpeedNames);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoTexture2D("_OutlineTex", "Texture", true);
|
||||
}
|
||||
}
|
||||
|
||||
DoSlider("_OutlineWidth", "Thickness");
|
||||
if (m_Material.HasProperty("_OutlineShininess"))
|
||||
{
|
||||
DoSlider("_OutlineShininess", "Gloss");
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel -= 1;
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
void DoUnderlayPanel()
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
s_UnderlayFeature.DoPopup(m_Editor, m_Material);
|
||||
DoColor("_UnderlayColor", "Color");
|
||||
DoSlider("_UnderlayOffsetX", "Offset X");
|
||||
DoSlider("_UnderlayOffsetY", "Offset Y");
|
||||
DoSlider("_UnderlayDilate", "Dilate");
|
||||
DoSlider("_UnderlaySoftness", "Softness");
|
||||
EditorGUI.indentLevel -= 1;
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
static GUIContent[] s_BevelTypeLabels =
|
||||
{
|
||||
new GUIContent("Outer Bevel"),
|
||||
new GUIContent("Inner Bevel")
|
||||
};
|
||||
|
||||
void DoBevelPanel()
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
DoPopup("_ShaderFlags", "Type", s_BevelTypeLabels);
|
||||
DoSlider("_Bevel", "Amount");
|
||||
DoSlider("_BevelOffset", "Offset");
|
||||
DoSlider("_BevelWidth", "Width");
|
||||
DoSlider("_BevelRoundness", "Roundness");
|
||||
DoSlider("_BevelClamp", "Clamp");
|
||||
EditorGUI.indentLevel -= 1;
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
void DoLocalLightingPanel()
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
DoSlider("_LightAngle", "Light Angle");
|
||||
DoColor("_SpecularColor", "Specular Color");
|
||||
DoSlider("_SpecularPower", "Specular Power");
|
||||
DoSlider("_Reflectivity", "Reflectivity Power");
|
||||
DoSlider("_Diffuse", "Diffuse Shadow");
|
||||
DoSlider("_Ambient", "Ambient Shadow");
|
||||
EditorGUI.indentLevel -= 1;
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
void DoSurfaceLightingPanel()
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
DoColor("_SpecColor", "Specular Color");
|
||||
EditorGUI.indentLevel -= 1;
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
void DoBumpMapPanel()
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
DoTexture2D("_BumpMap", "Texture");
|
||||
DoSlider("_BumpFace", "Face");
|
||||
DoSlider("_BumpOutline", "Outline");
|
||||
EditorGUI.indentLevel -= 1;
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
void DoEnvMapPanel()
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
DoColor("_ReflectFaceColor", "Face Color");
|
||||
DoColor("_ReflectOutlineColor", "Outline Color");
|
||||
DoCubeMap("_Cube", "Texture");
|
||||
DoVector3("_EnvMatrixRotation", "Rotation");
|
||||
EditorGUI.indentLevel -= 1;
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
void DoGlowPanel()
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
DoColor("_GlowColor", "Color");
|
||||
DoSlider("_GlowOffset", "Offset");
|
||||
DoSlider("_GlowInner", "Inner");
|
||||
DoSlider("_GlowOuter", "Outer");
|
||||
DoSlider("_GlowPower", "Power");
|
||||
EditorGUI.indentLevel -= 1;
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
void DoDebugPanel()
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
DoTexture2D("_MainTex", "Font Atlas");
|
||||
DoFloat("_GradientScale", "Gradient Scale");
|
||||
DoFloat("_TextureWidth", "Texture Width");
|
||||
DoFloat("_TextureHeight", "Texture Height");
|
||||
EditorGUILayout.Space();
|
||||
DoFloat("_ScaleX", "Scale X");
|
||||
DoFloat("_ScaleY", "Scale Y");
|
||||
|
||||
if (m_Material.HasProperty(ShaderUtilities.ID_Sharpness))
|
||||
DoSlider("_Sharpness", "Sharpness");
|
||||
|
||||
DoSlider("_PerspectiveFilter", "Perspective Filter");
|
||||
EditorGUILayout.Space();
|
||||
DoFloat("_VertexOffsetX", "Offset X");
|
||||
DoFloat("_VertexOffsetY", "Offset Y");
|
||||
|
||||
if (m_Material.HasProperty(ShaderUtilities.ID_MaskCoord))
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
s_MaskFeature.ReadState(m_Material);
|
||||
s_MaskFeature.DoPopup(m_Editor, m_Material);
|
||||
if (s_MaskFeature.Active)
|
||||
{
|
||||
DoMaskSubgroup();
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
DoVector("_ClipRect", "Clip Rect", s_LbrtVectorLabels);
|
||||
}
|
||||
else if (m_Material.HasProperty("_MaskTex"))
|
||||
{
|
||||
DoMaskTexSubgroup();
|
||||
}
|
||||
else if (m_Material.HasProperty(ShaderUtilities.ID_MaskSoftnessX))
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
DoFloat("_MaskSoftnessX", "Softness X");
|
||||
DoFloat("_MaskSoftnessY", "Softness Y");
|
||||
DoVector("_ClipRect", "Clip Rect", s_LbrtVectorLabels);
|
||||
}
|
||||
|
||||
if (m_Material.HasProperty(ShaderUtilities.ID_StencilID))
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
DoFloat("_Stencil", "Stencil ID");
|
||||
DoFloat("_StencilComp", "Stencil Comp");
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
bool useRatios = EditorGUILayout.Toggle("Use Ratios", !m_Material.IsKeywordEnabled("RATIOS_OFF"));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
m_Editor.RegisterPropertyChangeUndo("Use Ratios");
|
||||
if (useRatios)
|
||||
{
|
||||
m_Material.DisableKeyword("RATIOS_OFF");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Material.EnableKeyword("RATIOS_OFF");
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
DoFloat("_ScaleRatioA", "Scale Ratio A");
|
||||
DoFloat("_ScaleRatioB", "Scale Ratio B");
|
||||
DoFloat("_ScaleRatioC", "Scale Ratio C");
|
||||
EditorGUI.EndDisabledGroup();
|
||||
EditorGUI.indentLevel -= 1;
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
void DoMaskSubgroup()
|
||||
{
|
||||
DoVector("_MaskCoord", "Mask Bounds", s_XywhVectorLabels);
|
||||
if (Selection.activeGameObject != null)
|
||||
{
|
||||
Renderer renderer = Selection.activeGameObject.GetComponent<Renderer>();
|
||||
if (renderer != null)
|
||||
{
|
||||
Rect rect = EditorGUILayout.GetControlRect();
|
||||
rect.x += EditorGUIUtility.labelWidth;
|
||||
rect.width -= EditorGUIUtility.labelWidth;
|
||||
if (GUI.Button(rect, "Match Renderer Bounds"))
|
||||
{
|
||||
FindProperty("_MaskCoord", m_Properties).vectorValue = new Vector4(
|
||||
0,
|
||||
0,
|
||||
Mathf.Round(renderer.bounds.extents.x * 1000) / 1000,
|
||||
Mathf.Round(renderer.bounds.extents.y * 1000) / 1000
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s_MaskFeature.State == 1)
|
||||
{
|
||||
DoFloat("_MaskSoftnessX", "Softness X");
|
||||
DoFloat("_MaskSoftnessY", "Softness Y");
|
||||
}
|
||||
}
|
||||
|
||||
void DoMaskTexSubgroup()
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
DoTexture2D("_MaskTex", "Mask Texture");
|
||||
DoToggle("_MaskInverse", "Inverse Mask");
|
||||
DoColor("_MaskEdgeColor", "Edge Color");
|
||||
DoSlider("_MaskEdgeSoftness", "Edge Softness");
|
||||
DoSlider("_MaskWipeControl", "Wipe Position");
|
||||
DoFloat("_MaskSoftnessX", "Softness X");
|
||||
DoFloat("_MaskSoftnessY", "Softness Y");
|
||||
DoVector("_ClipRect", "Clip Rect", s_LbrtVectorLabels);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8413ca0e506d42a1a4bd9769f204ad16
|
||||
timeCreated: 1469844718
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,14 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TMPro
|
||||
{
|
||||
class TMP_SerializedPropertyHolder : ScriptableObject
|
||||
{
|
||||
public TMP_FontAsset fontAsset;
|
||||
public uint firstCharacter;
|
||||
public uint secondCharacter;
|
||||
|
||||
public TMP_GlyphPairAdjustmentRecord glyphPairAdjustmentRecord = new TMP_GlyphPairAdjustmentRecord(new TMP_GlyphAdjustmentRecord(), new TMP_GlyphAdjustmentRecord());
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c4a050f089abb04ebd4125e419f4548
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,341 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
|
||||
#pragma warning disable 0414 // Disabled a few warnings for not yet implemented features.
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
[CustomEditor(typeof(TMP_Settings))]
|
||||
public class TMP_SettingsEditor : Editor
|
||||
{
|
||||
internal class Styles
|
||||
{
|
||||
public static readonly GUIContent defaultFontAssetLabel = new GUIContent("Default Font Asset", "The Font Asset that will be assigned by default to newly created text objects when no Font Asset is specified.");
|
||||
public static readonly GUIContent defaultFontAssetPathLabel = new GUIContent("Path: Resources/", "The relative path to a Resources folder where the Font Assets and Material Presets are located.\nExample \"Fonts & Materials/\"");
|
||||
|
||||
public static readonly GUIContent fallbackFontAssetsLabel = new GUIContent("Fallback Font Assets", "The Font Assets that will be searched to locate and replace missing characters from a given Font Asset.");
|
||||
public static readonly GUIContent fallbackFontAssetsListLabel = new GUIContent("Fallback Font Assets List", "The Font Assets that will be searched to locate and replace missing characters from a given Font Asset.");
|
||||
|
||||
public static readonly GUIContent fallbackMaterialSettingsLabel = new GUIContent("Fallback Material Settings");
|
||||
public static readonly GUIContent matchMaterialPresetLabel = new GUIContent("Match Material Presets");
|
||||
|
||||
public static readonly GUIContent containerDefaultSettingsLabel = new GUIContent("Text Container Default Settings");
|
||||
|
||||
public static readonly GUIContent textMeshProLabel = new GUIContent("TextMeshPro");
|
||||
public static readonly GUIContent textMeshProUiLabel = new GUIContent("TextMeshPro UI");
|
||||
public static readonly GUIContent enableRaycastTarget = new GUIContent("Enable Raycast Target");
|
||||
public static readonly GUIContent autoSizeContainerLabel = new GUIContent("Auto Size Text Container", "Set the size of the text container to match the text.");
|
||||
|
||||
public static readonly GUIContent textComponentDefaultSettingsLabel = new GUIContent("Text Component Default Settings");
|
||||
public static readonly GUIContent defaultFontSize = new GUIContent("Default Font Size");
|
||||
public static readonly GUIContent autoSizeRatioLabel = new GUIContent("Text Auto Size Ratios");
|
||||
public static readonly GUIContent minLabel = new GUIContent("Min");
|
||||
public static readonly GUIContent maxLabel = new GUIContent("Max");
|
||||
|
||||
public static readonly GUIContent wordWrappingLabel = new GUIContent("Word Wrapping");
|
||||
public static readonly GUIContent kerningLabel = new GUIContent("Kerning");
|
||||
public static readonly GUIContent extraPaddingLabel = new GUIContent("Extra Padding");
|
||||
public static readonly GUIContent tintAllSpritesLabel = new GUIContent("Tint All Sprites");
|
||||
public static readonly GUIContent parseEscapeCharactersLabel = new GUIContent("Parse Escape Sequence");
|
||||
|
||||
public static readonly GUIContent dynamicFontSystemSettingsLabel = new GUIContent("Dynamic Font System Settings");
|
||||
public static readonly GUIContent getFontFeaturesAtRuntime = new GUIContent("Get Font Features at Runtime", "Determines if Glyph Adjustment Data will be retrieved from font files at runtime when new characters and glyphs are added to font assets.");
|
||||
|
||||
public static readonly GUIContent missingGlyphLabel = new GUIContent("Replacement Character", "The character to be displayed when the requested character is not found in any font asset or fallbacks.");
|
||||
public static readonly GUIContent disableWarningsLabel = new GUIContent("Disable warnings", "Disable warning messages in the Console.");
|
||||
|
||||
public static readonly GUIContent defaultSpriteAssetLabel = new GUIContent("Default Sprite Asset", "The Sprite Asset that will be assigned by default when using the <sprite> tag when no Sprite Asset is specified.");
|
||||
public static readonly GUIContent enableEmojiSupportLabel = new GUIContent("iOS Emoji Support", "Enables Emoji support for Touch Screen Keyboards on target devices.");
|
||||
public static readonly GUIContent spriteAssetsPathLabel = new GUIContent("Path: Resources/", "The relative path to a Resources folder where the Sprite Assets are located.\nExample \"Sprite Assets/\"");
|
||||
|
||||
public static readonly GUIContent defaultStyleSheetLabel = new GUIContent("Default Style Sheet", "The Style Sheet that will be used for all text objects in this project.");
|
||||
|
||||
public static readonly GUIContent colorGradientPresetsLabel = new GUIContent("Color Gradient Presets", "The relative path to a Resources folder where the Color Gradient Presets are located.\nExample \"Color Gradient Presets/\"");
|
||||
public static readonly GUIContent colorGradientsPathLabel = new GUIContent("Path: Resources/", "The relative path to a Resources folder where the Color Gradient Presets are located.\nExample \"Color Gradient Presets/\"");
|
||||
|
||||
public static readonly GUIContent lineBreakingLabel = new GUIContent("Line Breaking for Asian languages", "The text assets that contain the Leading and Following characters which define the rules for line breaking with Asian languages.");
|
||||
}
|
||||
|
||||
SerializedProperty m_PropFontAsset;
|
||||
SerializedProperty m_PropDefaultFontAssetPath;
|
||||
SerializedProperty m_PropDefaultFontSize;
|
||||
SerializedProperty m_PropDefaultAutoSizeMinRatio;
|
||||
SerializedProperty m_PropDefaultAutoSizeMaxRatio;
|
||||
SerializedProperty m_PropDefaultTextMeshProTextContainerSize;
|
||||
SerializedProperty m_PropDefaultTextMeshProUITextContainerSize;
|
||||
SerializedProperty m_PropAutoSizeTextContainer;
|
||||
SerializedProperty m_PropEnableRaycastTarget;
|
||||
|
||||
SerializedProperty m_PropSpriteAsset;
|
||||
SerializedProperty m_PropSpriteAssetPath;
|
||||
SerializedProperty m_PropEnableEmojiSupport;
|
||||
SerializedProperty m_PropStyleSheet;
|
||||
ReorderableList m_List;
|
||||
|
||||
SerializedProperty m_PropColorGradientPresetsPath;
|
||||
|
||||
SerializedProperty m_PropMatchMaterialPreset;
|
||||
SerializedProperty m_PropWordWrapping;
|
||||
SerializedProperty m_PropKerning;
|
||||
SerializedProperty m_PropExtraPadding;
|
||||
SerializedProperty m_PropTintAllSprites;
|
||||
SerializedProperty m_PropParseEscapeCharacters;
|
||||
SerializedProperty m_PropMissingGlyphCharacter;
|
||||
|
||||
SerializedProperty m_GetFontFeaturesAtRuntime;
|
||||
|
||||
SerializedProperty m_PropWarningsDisabled;
|
||||
|
||||
SerializedProperty m_PropLeadingCharacters;
|
||||
SerializedProperty m_PropFollowingCharacters;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
if (target == null)
|
||||
return;
|
||||
|
||||
m_PropFontAsset = serializedObject.FindProperty("m_defaultFontAsset");
|
||||
m_PropDefaultFontAssetPath = serializedObject.FindProperty("m_defaultFontAssetPath");
|
||||
m_PropDefaultFontSize = serializedObject.FindProperty("m_defaultFontSize");
|
||||
m_PropDefaultAutoSizeMinRatio = serializedObject.FindProperty("m_defaultAutoSizeMinRatio");
|
||||
m_PropDefaultAutoSizeMaxRatio = serializedObject.FindProperty("m_defaultAutoSizeMaxRatio");
|
||||
m_PropDefaultTextMeshProTextContainerSize = serializedObject.FindProperty("m_defaultTextMeshProTextContainerSize");
|
||||
m_PropDefaultTextMeshProUITextContainerSize = serializedObject.FindProperty("m_defaultTextMeshProUITextContainerSize");
|
||||
m_PropAutoSizeTextContainer = serializedObject.FindProperty("m_autoSizeTextContainer");
|
||||
m_PropEnableRaycastTarget = serializedObject.FindProperty("m_EnableRaycastTarget");
|
||||
|
||||
m_PropSpriteAsset = serializedObject.FindProperty("m_defaultSpriteAsset");
|
||||
m_PropSpriteAssetPath = serializedObject.FindProperty("m_defaultSpriteAssetPath");
|
||||
m_PropEnableEmojiSupport = serializedObject.FindProperty("m_enableEmojiSupport");
|
||||
m_PropStyleSheet = serializedObject.FindProperty("m_defaultStyleSheet");
|
||||
m_PropColorGradientPresetsPath = serializedObject.FindProperty("m_defaultColorGradientPresetsPath");
|
||||
|
||||
m_List = new ReorderableList(serializedObject, serializedObject.FindProperty("m_fallbackFontAssets"), true, true, true, true);
|
||||
|
||||
m_List.drawElementCallback = (rect, index, isActive, isFocused) =>
|
||||
{
|
||||
var element = m_List.serializedProperty.GetArrayElementAtIndex(index);
|
||||
rect.y += 2;
|
||||
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element, GUIContent.none);
|
||||
};
|
||||
|
||||
m_List.drawHeaderCallback = rect =>
|
||||
{
|
||||
EditorGUI.LabelField(rect, Styles.fallbackFontAssetsListLabel);
|
||||
};
|
||||
|
||||
m_PropMatchMaterialPreset = serializedObject.FindProperty("m_matchMaterialPreset");
|
||||
|
||||
m_PropWordWrapping = serializedObject.FindProperty("m_enableWordWrapping");
|
||||
m_PropKerning = serializedObject.FindProperty("m_enableKerning");
|
||||
m_PropExtraPadding = serializedObject.FindProperty("m_enableExtraPadding");
|
||||
m_PropTintAllSprites = serializedObject.FindProperty("m_enableTintAllSprites");
|
||||
m_PropParseEscapeCharacters = serializedObject.FindProperty("m_enableParseEscapeCharacters");
|
||||
m_PropMissingGlyphCharacter = serializedObject.FindProperty("m_missingGlyphCharacter");
|
||||
|
||||
m_PropWarningsDisabled = serializedObject.FindProperty("m_warningsDisabled");
|
||||
|
||||
m_GetFontFeaturesAtRuntime = serializedObject.FindProperty("m_GetFontFeaturesAtRuntime");
|
||||
|
||||
m_PropLeadingCharacters = serializedObject.FindProperty("m_leadingCharacters");
|
||||
m_PropFollowingCharacters = serializedObject.FindProperty("m_followingCharacters");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
float labelWidth = EditorGUIUtility.labelWidth;
|
||||
float fieldWidth = EditorGUIUtility.fieldWidth;
|
||||
|
||||
// TextMeshPro Font Info Panel
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
// FONT ASSET
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.Label(Styles.defaultFontAssetLabel, EditorStyles.boldLabel);
|
||||
EditorGUI.indentLevel = 1;
|
||||
EditorGUILayout.PropertyField(m_PropFontAsset, Styles.defaultFontAssetLabel);
|
||||
EditorGUILayout.PropertyField(m_PropDefaultFontAssetPath, Styles.defaultFontAssetPathLabel);
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
// FALLBACK FONT ASSETs
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.Label(Styles.fallbackFontAssetsLabel, EditorStyles.boldLabel);
|
||||
m_List.DoLayoutList();
|
||||
|
||||
GUILayout.Label(Styles.fallbackMaterialSettingsLabel, EditorStyles.boldLabel);
|
||||
EditorGUI.indentLevel = 1;
|
||||
EditorGUILayout.PropertyField(m_PropMatchMaterialPreset, Styles.matchMaterialPresetLabel);
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
// MISSING GLYPHS
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.Label(Styles.dynamicFontSystemSettingsLabel, EditorStyles.boldLabel);
|
||||
EditorGUI.indentLevel = 1;
|
||||
EditorGUILayout.PropertyField(m_GetFontFeaturesAtRuntime, Styles.getFontFeaturesAtRuntime);
|
||||
EditorGUILayout.PropertyField(m_PropMissingGlyphCharacter, Styles.missingGlyphLabel);
|
||||
EditorGUILayout.PropertyField(m_PropWarningsDisabled, Styles.disableWarningsLabel);
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
// TEXT OBJECT DEFAULT PROPERTIES
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.Label(Styles.containerDefaultSettingsLabel, EditorStyles.boldLabel);
|
||||
EditorGUI.indentLevel = 1;
|
||||
|
||||
EditorGUILayout.PropertyField(m_PropDefaultTextMeshProTextContainerSize, Styles.textMeshProLabel);
|
||||
EditorGUILayout.PropertyField(m_PropDefaultTextMeshProUITextContainerSize, Styles.textMeshProUiLabel);
|
||||
EditorGUILayout.PropertyField(m_PropEnableRaycastTarget, Styles.enableRaycastTarget);
|
||||
EditorGUILayout.PropertyField(m_PropAutoSizeTextContainer, Styles.autoSizeContainerLabel);
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
GUILayout.Label(Styles.textComponentDefaultSettingsLabel, EditorStyles.boldLabel);
|
||||
EditorGUI.indentLevel = 1;
|
||||
EditorGUILayout.PropertyField(m_PropDefaultFontSize, Styles.defaultFontSize);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
{
|
||||
EditorGUILayout.PrefixLabel(Styles.autoSizeRatioLabel);
|
||||
EditorGUIUtility.labelWidth = 32;
|
||||
EditorGUIUtility.fieldWidth = 10;
|
||||
|
||||
EditorGUI.indentLevel = 0;
|
||||
EditorGUILayout.PropertyField(m_PropDefaultAutoSizeMinRatio, Styles.minLabel);
|
||||
EditorGUILayout.PropertyField(m_PropDefaultAutoSizeMaxRatio, Styles.maxLabel);
|
||||
EditorGUI.indentLevel = 1;
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUIUtility.labelWidth = labelWidth;
|
||||
EditorGUIUtility.fieldWidth = fieldWidth;
|
||||
|
||||
EditorGUILayout.PropertyField(m_PropWordWrapping, Styles.wordWrappingLabel);
|
||||
EditorGUILayout.PropertyField(m_PropKerning, Styles.kerningLabel);
|
||||
|
||||
EditorGUILayout.PropertyField(m_PropExtraPadding, Styles.extraPaddingLabel);
|
||||
EditorGUILayout.PropertyField(m_PropTintAllSprites, Styles.tintAllSpritesLabel);
|
||||
|
||||
EditorGUILayout.PropertyField(m_PropParseEscapeCharacters, Styles.parseEscapeCharactersLabel);
|
||||
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
// SPRITE ASSET
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.Label(Styles.defaultSpriteAssetLabel, EditorStyles.boldLabel);
|
||||
EditorGUI.indentLevel = 1;
|
||||
EditorGUILayout.PropertyField(m_PropSpriteAsset, Styles.defaultSpriteAssetLabel);
|
||||
EditorGUILayout.PropertyField(m_PropEnableEmojiSupport, Styles.enableEmojiSupportLabel);
|
||||
EditorGUILayout.PropertyField(m_PropSpriteAssetPath, Styles.spriteAssetsPathLabel);
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
// STYLE SHEET
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.Label(Styles.defaultStyleSheetLabel, EditorStyles.boldLabel);
|
||||
EditorGUI.indentLevel = 1;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(m_PropStyleSheet, Styles.defaultStyleSheetLabel);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
TMP_StyleSheet.UpdateStyleSheet();
|
||||
}
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
// COLOR GRADIENT PRESETS
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.Label(Styles.colorGradientPresetsLabel, EditorStyles.boldLabel);
|
||||
EditorGUI.indentLevel = 1;
|
||||
EditorGUILayout.PropertyField(m_PropColorGradientPresetsPath, Styles.colorGradientsPathLabel);
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
// LINE BREAKING RULE
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.Label(Styles.lineBreakingLabel, EditorStyles.boldLabel);
|
||||
EditorGUI.indentLevel = 1;
|
||||
EditorGUILayout.PropertyField(m_PropLeadingCharacters);
|
||||
EditorGUILayout.PropertyField(m_PropFollowingCharacters);
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (serializedObject.ApplyModifiedProperties())
|
||||
{
|
||||
EditorUtility.SetDirty(target);
|
||||
TMPro_EventManager.ON_TMP_SETTINGS_CHANGED();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
class TMP_ResourceImporterProvider : SettingsProvider
|
||||
{
|
||||
TMP_PackageResourceImporter m_ResourceImporter;
|
||||
|
||||
public TMP_ResourceImporterProvider()
|
||||
: base("Project/TextMesh Pro", SettingsScope.Project)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnGUI(string searchContext)
|
||||
{
|
||||
// Lazy creation that supports domain reload
|
||||
if (m_ResourceImporter == null)
|
||||
m_ResourceImporter = new TMP_PackageResourceImporter();
|
||||
|
||||
m_ResourceImporter.OnGUI();
|
||||
}
|
||||
|
||||
public override void OnDeactivate()
|
||||
{
|
||||
if (m_ResourceImporter != null)
|
||||
m_ResourceImporter.OnDestroy();
|
||||
}
|
||||
|
||||
static UnityEngine.Object GetTMPSettings()
|
||||
{
|
||||
return Resources.Load<TMP_Settings>("TMP Settings");
|
||||
}
|
||||
|
||||
[SettingsProviderGroup]
|
||||
static SettingsProvider[] CreateTMPSettingsProvider()
|
||||
{
|
||||
var providers = new List<SettingsProvider> { new TMP_ResourceImporterProvider() };
|
||||
|
||||
if (GetTMPSettings() != null)
|
||||
{
|
||||
var provider = new AssetSettingsProvider("Project/TextMesh Pro/Settings", GetTMPSettings);
|
||||
provider.PopulateSearchKeywordsFromGUIContentProperties<TMP_SettingsEditor.Styles>();
|
||||
providers.Add(provider);
|
||||
}
|
||||
|
||||
return providers.ToArray();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0386b6eb838c47138cd51d1c1b879a35
|
||||
timeCreated: 1436658550
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,896 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.TextCore;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
[CustomEditor(typeof(TMP_SpriteAsset))]
|
||||
public class TMP_SpriteAssetEditor : Editor
|
||||
{
|
||||
struct UI_PanelState
|
||||
{
|
||||
public static bool spriteAssetInfoPanel = true;
|
||||
public static bool fallbackSpriteAssetPanel = true;
|
||||
public static bool spriteCharacterTablePanel;
|
||||
public static bool spriteGlyphTablePanel;
|
||||
}
|
||||
|
||||
private static string[] s_UiStateLabel = new string[] { "<i>(Click to collapse)</i> ", "<i>(Click to expand)</i> " };
|
||||
|
||||
int m_moveToIndex;
|
||||
int m_selectedElement = -1;
|
||||
int m_CurrentCharacterPage;
|
||||
int m_CurrentGlyphPage;
|
||||
|
||||
const string k_UndoRedo = "UndoRedoPerformed";
|
||||
|
||||
string m_CharacterSearchPattern;
|
||||
List<int> m_CharacterSearchList;
|
||||
bool m_IsCharacterSearchDirty;
|
||||
|
||||
string m_GlyphSearchPattern;
|
||||
List<int> m_GlyphSearchList;
|
||||
bool m_IsGlyphSearchDirty;
|
||||
|
||||
SerializedProperty m_spriteAtlas_prop;
|
||||
SerializedProperty m_material_prop;
|
||||
SerializedProperty m_SpriteCharacterTableProperty;
|
||||
SerializedProperty m_SpriteGlyphTableProperty;
|
||||
ReorderableList m_fallbackSpriteAssetList;
|
||||
|
||||
TMP_SpriteAsset m_SpriteAsset;
|
||||
|
||||
bool isAssetDirty;
|
||||
|
||||
float m_xOffset;
|
||||
float m_yOffset;
|
||||
float m_xAdvance;
|
||||
float m_scale;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
m_SpriteAsset = target as TMP_SpriteAsset;
|
||||
|
||||
m_spriteAtlas_prop = serializedObject.FindProperty("spriteSheet");
|
||||
m_material_prop = serializedObject.FindProperty("material");
|
||||
m_SpriteCharacterTableProperty = serializedObject.FindProperty("m_SpriteCharacterTable");
|
||||
m_SpriteGlyphTableProperty = serializedObject.FindProperty("m_SpriteGlyphTable");
|
||||
|
||||
// Fallback TMP Sprite Asset list
|
||||
m_fallbackSpriteAssetList = new ReorderableList(serializedObject, serializedObject.FindProperty("fallbackSpriteAssets"), true, true, true, true);
|
||||
|
||||
m_fallbackSpriteAssetList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
|
||||
{
|
||||
var element = m_fallbackSpriteAssetList.serializedProperty.GetArrayElementAtIndex(index);
|
||||
rect.y += 2;
|
||||
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element, GUIContent.none);
|
||||
};
|
||||
|
||||
m_fallbackSpriteAssetList.drawHeaderCallback = rect =>
|
||||
{
|
||||
EditorGUI.LabelField(rect, new GUIContent("Fallback Sprite Asset List", "Select the Sprite Assets that will be searched and used as fallback when a given sprite is missing from this sprite asset."));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
|
||||
//Debug.Log("OnInspectorGUI Called.");
|
||||
Event currentEvent = Event.current;
|
||||
string evt_cmd = currentEvent.commandName; // Get Current Event CommandName to check for Undo Events
|
||||
|
||||
serializedObject.Update();
|
||||
|
||||
Rect rect;
|
||||
|
||||
// TEXTMESHPRO SPRITE INFO PANEL
|
||||
GUILayout.Label("Sprite Info", EditorStyles.boldLabel);
|
||||
EditorGUI.indentLevel = 1;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(m_spriteAtlas_prop , new GUIContent("Sprite Atlas"));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
// Assign the new sprite atlas texture to the current material
|
||||
Texture2D tex = m_spriteAtlas_prop.objectReferenceValue as Texture2D;
|
||||
if (tex != null)
|
||||
{
|
||||
Material mat = m_material_prop.objectReferenceValue as Material;
|
||||
if (mat != null)
|
||||
mat.mainTexture = tex;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(m_material_prop, new GUIContent("Default Material"));
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// FALLBACK SPRITE ASSETS
|
||||
EditorGUI.indentLevel = 0;
|
||||
UI_PanelState.fallbackSpriteAssetPanel = EditorGUILayout.Foldout(UI_PanelState.fallbackSpriteAssetPanel, new GUIContent("Fallback Sprite Assets", "Select the Sprite Assets that will be searched and used as fallback when a given sprite is missing from this sprite asset."), true, TMP_UIStyleManager.boldFoldout);
|
||||
|
||||
if (UI_PanelState.fallbackSpriteAssetPanel)
|
||||
{
|
||||
m_fallbackSpriteAssetList.DoLayoutList();
|
||||
}
|
||||
|
||||
// SPRITE CHARACTER TABLE
|
||||
#region Display Sprite Character Table
|
||||
EditorGUI.indentLevel = 0;
|
||||
rect = EditorGUILayout.GetControlRect(false, 24);
|
||||
|
||||
if (GUI.Button(rect, new GUIContent("<b>Sprite Character Table</b>", "List of sprite characters contained in this sprite asset."), TMP_UIStyleManager.sectionHeader))
|
||||
UI_PanelState.spriteCharacterTablePanel = !UI_PanelState.spriteCharacterTablePanel;
|
||||
|
||||
GUI.Label(rect, (UI_PanelState.spriteCharacterTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
|
||||
|
||||
if (UI_PanelState.spriteCharacterTablePanel)
|
||||
{
|
||||
int arraySize = m_SpriteCharacterTableProperty.arraySize;
|
||||
int itemsPerPage = 10;
|
||||
|
||||
// Display Glyph Management Tools
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.ExpandWidth(true));
|
||||
{
|
||||
// Search Bar implementation
|
||||
#region DISPLAY SEARCH BAR
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
{
|
||||
EditorGUIUtility.labelWidth = 110f;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
string searchPattern = EditorGUILayout.TextField("Sprite Search", m_CharacterSearchPattern, "SearchTextField");
|
||||
if (EditorGUI.EndChangeCheck() || m_IsCharacterSearchDirty)
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchPattern) == false)
|
||||
{
|
||||
//GUIUtility.keyboardControl = 0;
|
||||
m_CharacterSearchPattern = searchPattern.ToLower(System.Globalization.CultureInfo.InvariantCulture).Trim();
|
||||
|
||||
// Search Glyph Table for potential matches
|
||||
SearchCharacterTable(m_CharacterSearchPattern, ref m_CharacterSearchList);
|
||||
}
|
||||
else
|
||||
m_CharacterSearchPattern = null;
|
||||
|
||||
m_IsCharacterSearchDirty = false;
|
||||
}
|
||||
|
||||
string styleName = string.IsNullOrEmpty(m_CharacterSearchPattern) ? "SearchCancelButtonEmpty" : "SearchCancelButton";
|
||||
if (GUILayout.Button(GUIContent.none, styleName))
|
||||
{
|
||||
GUIUtility.keyboardControl = 0;
|
||||
m_CharacterSearchPattern = string.Empty;
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
#endregion
|
||||
|
||||
// Display Page Navigation
|
||||
if (!string.IsNullOrEmpty(m_CharacterSearchPattern))
|
||||
arraySize = m_CharacterSearchList.Count;
|
||||
|
||||
// Display Page Navigation
|
||||
DisplayPageNavigation(ref m_CurrentCharacterPage, arraySize, itemsPerPage);
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (arraySize > 0)
|
||||
{
|
||||
// Display each SpriteInfo entry using the SpriteInfo property drawer.
|
||||
for (int i = itemsPerPage * m_CurrentCharacterPage; i < arraySize && i < itemsPerPage * (m_CurrentCharacterPage + 1); i++)
|
||||
{
|
||||
// Define the start of the selection region of the element.
|
||||
Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
|
||||
|
||||
int elementIndex = i;
|
||||
if (!string.IsNullOrEmpty(m_CharacterSearchPattern))
|
||||
elementIndex = m_CharacterSearchList[i];
|
||||
|
||||
SerializedProperty spriteCharacterProperty = m_SpriteCharacterTableProperty.GetArrayElementAtIndex(elementIndex);
|
||||
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(i != m_selectedElement);
|
||||
{
|
||||
EditorGUILayout.PropertyField(spriteCharacterProperty);
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw & Handle Section Area
|
||||
if (m_selectedElement == i)
|
||||
{
|
||||
// Draw selection highlight
|
||||
TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
|
||||
|
||||
// Draw options to MoveUp, MoveDown, Add or Remove Sprites
|
||||
Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 1f);
|
||||
controlRect.width /= 8;
|
||||
|
||||
// Move sprite up.
|
||||
bool guiEnabled = GUI.enabled;
|
||||
if (i == 0) { GUI.enabled = false; }
|
||||
if (GUI.Button(controlRect, "Up"))
|
||||
{
|
||||
SwapCharacterElements(i, i - 1);
|
||||
}
|
||||
GUI.enabled = guiEnabled;
|
||||
|
||||
// Move sprite down.
|
||||
controlRect.x += controlRect.width;
|
||||
if (i == arraySize - 1) { GUI.enabled = false; }
|
||||
if (GUI.Button(controlRect, "Down"))
|
||||
{
|
||||
SwapCharacterElements(i, i + 1);
|
||||
}
|
||||
GUI.enabled = guiEnabled;
|
||||
|
||||
// Move sprite to new index
|
||||
controlRect.x += controlRect.width * 2;
|
||||
//if (i == arraySize - 1) { GUI.enabled = false; }
|
||||
m_moveToIndex = EditorGUI.IntField(controlRect, m_moveToIndex);
|
||||
controlRect.x -= controlRect.width;
|
||||
if (GUI.Button(controlRect, "Goto"))
|
||||
{
|
||||
MoveCharacterToIndex(i, m_moveToIndex);
|
||||
}
|
||||
//controlRect.x += controlRect.width;
|
||||
GUI.enabled = guiEnabled;
|
||||
|
||||
// Add new Sprite
|
||||
controlRect.x += controlRect.width * 4;
|
||||
if (GUI.Button(controlRect, "+"))
|
||||
{
|
||||
m_SpriteCharacterTableProperty.arraySize += 1;
|
||||
|
||||
int index = m_SpriteCharacterTableProperty.arraySize - 1;
|
||||
|
||||
SerializedProperty spriteInfo_prop = m_SpriteCharacterTableProperty.GetArrayElementAtIndex(index);
|
||||
|
||||
// Copy properties of the selected element
|
||||
CopyCharacterSerializedProperty(m_SpriteCharacterTableProperty.GetArrayElementAtIndex(elementIndex), ref spriteInfo_prop);
|
||||
|
||||
//spriteInfo_prop.FindPropertyRelative("m_Index").intValue = index;
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
m_IsCharacterSearchDirty = true;
|
||||
}
|
||||
|
||||
// Delete selected Sprite
|
||||
controlRect.x += controlRect.width;
|
||||
if (m_selectedElement == -1) GUI.enabled = false;
|
||||
if (GUI.Button(controlRect, "-"))
|
||||
{
|
||||
m_SpriteCharacterTableProperty.DeleteArrayElementAtIndex(elementIndex);
|
||||
|
||||
m_selectedElement = -1;
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
m_IsCharacterSearchDirty = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DisplayPageNavigation(ref m_CurrentCharacterPage, arraySize, itemsPerPage);
|
||||
|
||||
EditorGUIUtility.labelWidth = 40f;
|
||||
EditorGUIUtility.fieldWidth = 20f;
|
||||
|
||||
GUILayout.Space(5f);
|
||||
|
||||
// GLOBAL TOOLS
|
||||
#region Global Tools
|
||||
/*
|
||||
GUI.enabled = true;
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
rect = EditorGUILayout.GetControlRect(false, 40);
|
||||
|
||||
float width = (rect.width - 75f) / 4;
|
||||
EditorGUI.LabelField(rect, "Global Offsets & Scale", EditorStyles.boldLabel);
|
||||
|
||||
|
||||
rect.x += 70;
|
||||
bool old_ChangedState = GUI.changed;
|
||||
|
||||
GUI.changed = false;
|
||||
m_xOffset = EditorGUI.FloatField(new Rect(rect.x + 5f + width * 0, rect.y + 20, width - 5f, 18), new GUIContent("OX:"), m_xOffset);
|
||||
if (GUI.changed) UpdateGlobalProperty("m_HorizontalBearingX", m_xOffset);
|
||||
|
||||
m_yOffset = EditorGUI.FloatField(new Rect(rect.x + 5f + width * 1, rect.y + 20, width - 5f, 18), new GUIContent("OY:"), m_yOffset);
|
||||
if (GUI.changed) UpdateGlobalProperty("m_HorizontalBearingY", m_yOffset);
|
||||
|
||||
m_xAdvance = EditorGUI.FloatField(new Rect(rect.x + 5f + width * 2, rect.y + 20, width - 5f, 18), new GUIContent("ADV."), m_xAdvance);
|
||||
if (GUI.changed) UpdateGlobalProperty("m_HorizontalAdvance", m_xAdvance);
|
||||
|
||||
m_scale = EditorGUI.FloatField(new Rect(rect.x + 5f + width * 3, rect.y + 20, width - 5f, 18), new GUIContent("SF."), m_scale);
|
||||
if (GUI.changed) UpdateGlobalProperty("m_Scale", m_scale);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
GUI.changed = old_ChangedState;
|
||||
*/
|
||||
#endregion
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
// SPRITE GLYPH TABLE
|
||||
#region Display Sprite Glyph Table
|
||||
EditorGUI.indentLevel = 0;
|
||||
rect = EditorGUILayout.GetControlRect(false, 24);
|
||||
|
||||
if (GUI.Button(rect, new GUIContent("<b>Sprite Glyph Table</b>", "A list of the SpriteGlyphs contained in this sprite asset."), TMP_UIStyleManager.sectionHeader))
|
||||
UI_PanelState.spriteGlyphTablePanel = !UI_PanelState.spriteGlyphTablePanel;
|
||||
|
||||
GUI.Label(rect, (UI_PanelState.spriteGlyphTablePanel ? "" : s_UiStateLabel[1]), TMP_UIStyleManager.rightLabel);
|
||||
|
||||
if (UI_PanelState.spriteGlyphTablePanel)
|
||||
{
|
||||
int arraySize = m_SpriteGlyphTableProperty.arraySize;
|
||||
int itemsPerPage = 10;
|
||||
|
||||
// Display Glyph Management Tools
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.ExpandWidth(true));
|
||||
{
|
||||
// Search Bar implementation
|
||||
#region DISPLAY SEARCH BAR
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
{
|
||||
EditorGUIUtility.labelWidth = 110f;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
string searchPattern = EditorGUILayout.TextField("Sprite Search", m_GlyphSearchPattern, "SearchTextField");
|
||||
if (EditorGUI.EndChangeCheck() || m_IsGlyphSearchDirty)
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchPattern) == false)
|
||||
{
|
||||
//GUIUtility.keyboardControl = 0;
|
||||
m_GlyphSearchPattern = searchPattern.ToLower(System.Globalization.CultureInfo.InvariantCulture).Trim();
|
||||
|
||||
// Search Glyph Table for potential matches
|
||||
SearchCharacterTable(m_GlyphSearchPattern, ref m_GlyphSearchList);
|
||||
}
|
||||
else
|
||||
m_GlyphSearchPattern = null;
|
||||
|
||||
m_IsGlyphSearchDirty = false;
|
||||
}
|
||||
|
||||
string styleName = string.IsNullOrEmpty(m_GlyphSearchPattern) ? "SearchCancelButtonEmpty" : "SearchCancelButton";
|
||||
if (GUILayout.Button(GUIContent.none, styleName))
|
||||
{
|
||||
GUIUtility.keyboardControl = 0;
|
||||
m_GlyphSearchPattern = string.Empty;
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
#endregion
|
||||
|
||||
// Display Page Navigation
|
||||
if (!string.IsNullOrEmpty(m_GlyphSearchPattern))
|
||||
arraySize = m_GlyphSearchList.Count;
|
||||
|
||||
// Display Page Navigation
|
||||
DisplayPageNavigation(ref m_CurrentGlyphPage, arraySize, itemsPerPage);
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (arraySize > 0)
|
||||
{
|
||||
// Display each SpriteInfo entry using the SpriteInfo property drawer.
|
||||
for (int i = itemsPerPage * m_CurrentGlyphPage; i < arraySize && i < itemsPerPage * (m_CurrentGlyphPage + 1); i++)
|
||||
{
|
||||
// Define the start of the selection region of the element.
|
||||
Rect elementStartRegion = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true));
|
||||
|
||||
int elementIndex = i;
|
||||
if (!string.IsNullOrEmpty(m_GlyphSearchPattern))
|
||||
elementIndex = m_GlyphSearchList[i];
|
||||
|
||||
SerializedProperty spriteGlyphProperty = m_SpriteGlyphTableProperty.GetArrayElementAtIndex(elementIndex);
|
||||
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(i != m_selectedElement);
|
||||
{
|
||||
EditorGUILayout.PropertyField(spriteGlyphProperty);
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw & Handle Section Area
|
||||
if (m_selectedElement == i)
|
||||
{
|
||||
// Draw selection highlight
|
||||
TMP_EditorUtility.DrawBox(selectionArea, 2f, new Color32(40, 192, 255, 255));
|
||||
|
||||
// Draw options to MoveUp, MoveDown, Add or Remove Sprites
|
||||
Rect controlRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 1f);
|
||||
controlRect.width /= 8;
|
||||
|
||||
// Move sprite up.
|
||||
bool guiEnabled = GUI.enabled;
|
||||
if (i == 0) { GUI.enabled = false; }
|
||||
if (GUI.Button(controlRect, "Up"))
|
||||
{
|
||||
SwapGlyphElements(i, i - 1);
|
||||
}
|
||||
GUI.enabled = guiEnabled;
|
||||
|
||||
// Move sprite down.
|
||||
controlRect.x += controlRect.width;
|
||||
if (i == arraySize - 1) { GUI.enabled = false; }
|
||||
if (GUI.Button(controlRect, "Down"))
|
||||
{
|
||||
SwapGlyphElements(i, i + 1);
|
||||
}
|
||||
GUI.enabled = guiEnabled;
|
||||
|
||||
// Move sprite to new index
|
||||
controlRect.x += controlRect.width * 2;
|
||||
//if (i == arraySize - 1) { GUI.enabled = false; }
|
||||
m_moveToIndex = EditorGUI.IntField(controlRect, m_moveToIndex);
|
||||
controlRect.x -= controlRect.width;
|
||||
if (GUI.Button(controlRect, "Goto"))
|
||||
{
|
||||
MoveGlyphToIndex(i, m_moveToIndex);
|
||||
}
|
||||
//controlRect.x += controlRect.width;
|
||||
GUI.enabled = guiEnabled;
|
||||
|
||||
// Add new Sprite
|
||||
controlRect.x += controlRect.width * 4;
|
||||
if (GUI.Button(controlRect, "+"))
|
||||
{
|
||||
m_SpriteGlyphTableProperty.arraySize += 1;
|
||||
|
||||
int index = m_SpriteGlyphTableProperty.arraySize - 1;
|
||||
|
||||
SerializedProperty newSpriteGlyphProperty = m_SpriteGlyphTableProperty.GetArrayElementAtIndex(index);
|
||||
|
||||
// Copy properties of the selected element
|
||||
CopyGlyphSerializedProperty(m_SpriteGlyphTableProperty.GetArrayElementAtIndex(elementIndex), ref newSpriteGlyphProperty);
|
||||
|
||||
newSpriteGlyphProperty.FindPropertyRelative("m_Index").intValue = index;
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
m_IsGlyphSearchDirty = true;
|
||||
|
||||
//m_SpriteAsset.UpdateLookupTables();
|
||||
}
|
||||
|
||||
// Delete selected Sprite
|
||||
controlRect.x += controlRect.width;
|
||||
if (m_selectedElement == -1) GUI.enabled = false;
|
||||
if (GUI.Button(controlRect, "-"))
|
||||
{
|
||||
SerializedProperty selectedSpriteGlyphProperty = m_SpriteGlyphTableProperty.GetArrayElementAtIndex(elementIndex);
|
||||
|
||||
int selectedGlyphIndex = selectedSpriteGlyphProperty.FindPropertyRelative("m_Index").intValue;
|
||||
|
||||
m_SpriteGlyphTableProperty.DeleteArrayElementAtIndex(elementIndex);
|
||||
|
||||
// Remove all Sprite Characters referencing this glyph.
|
||||
for (int j = 0; j < m_SpriteCharacterTableProperty.arraySize; j++)
|
||||
{
|
||||
int glyphIndex = m_SpriteCharacterTableProperty.GetArrayElementAtIndex(j).FindPropertyRelative("m_GlyphIndex").intValue;
|
||||
|
||||
if (glyphIndex == selectedGlyphIndex)
|
||||
{
|
||||
// Remove character
|
||||
m_SpriteCharacterTableProperty.DeleteArrayElementAtIndex(j);
|
||||
}
|
||||
}
|
||||
|
||||
m_selectedElement = -1;
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
m_IsGlyphSearchDirty = true;
|
||||
|
||||
//m_SpriteAsset.UpdateLookupTables();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DisplayPageNavigation(ref m_CurrentGlyphPage, arraySize, itemsPerPage);
|
||||
|
||||
EditorGUIUtility.labelWidth = 40f;
|
||||
EditorGUIUtility.fieldWidth = 20f;
|
||||
|
||||
GUILayout.Space(5f);
|
||||
|
||||
// GLOBAL TOOLS
|
||||
#region Global Tools
|
||||
GUI.enabled = true;
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
rect = EditorGUILayout.GetControlRect(false, 40);
|
||||
|
||||
float width = (rect.width - 75f) / 4;
|
||||
EditorGUI.LabelField(rect, "Global Offsets & Scale", EditorStyles.boldLabel);
|
||||
|
||||
|
||||
rect.x += 70;
|
||||
bool old_ChangedState = GUI.changed;
|
||||
|
||||
GUI.changed = false;
|
||||
m_xOffset = EditorGUI.FloatField(new Rect(rect.x + 5f + width * 0, rect.y + 20, width - 5f, 18), new GUIContent("OX:"), m_xOffset);
|
||||
if (GUI.changed) UpdateGlobalProperty("m_HorizontalBearingX", m_xOffset);
|
||||
|
||||
m_yOffset = EditorGUI.FloatField(new Rect(rect.x + 5f + width * 1, rect.y + 20, width - 5f, 18), new GUIContent("OY:"), m_yOffset);
|
||||
if (GUI.changed) UpdateGlobalProperty("m_HorizontalBearingY", m_yOffset);
|
||||
|
||||
m_xAdvance = EditorGUI.FloatField(new Rect(rect.x + 5f + width * 2, rect.y + 20, width - 5f, 18), new GUIContent("ADV."), m_xAdvance);
|
||||
if (GUI.changed) UpdateGlobalProperty("m_HorizontalAdvance", m_xAdvance);
|
||||
|
||||
m_scale = EditorGUI.FloatField(new Rect(rect.x + 5f + width * 3, rect.y + 20, width - 5f, 18), new GUIContent("SF."), m_scale);
|
||||
if (GUI.changed) UpdateGlobalProperty("m_Scale", m_scale);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
#endregion
|
||||
|
||||
GUI.changed = old_ChangedState;
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
if (serializedObject.ApplyModifiedProperties() || evt_cmd == k_UndoRedo || isAssetDirty)
|
||||
{
|
||||
if (m_SpriteAsset.m_IsSpriteAssetLookupTablesDirty || evt_cmd == k_UndoRedo)
|
||||
m_SpriteAsset.UpdateLookupTables();
|
||||
|
||||
TMPro_EventManager.ON_SPRITE_ASSET_PROPERTY_CHANGED(true, m_SpriteAsset);
|
||||
|
||||
isAssetDirty = false;
|
||||
EditorUtility.SetDirty(target);
|
||||
}
|
||||
|
||||
// Clear selection if mouse event was not consumed.
|
||||
GUI.enabled = true;
|
||||
if (currentEvent.type == EventType.MouseDown && currentEvent.button == 0)
|
||||
m_selectedElement = -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="arraySize"></param>
|
||||
/// <param name="itemsPerPage"></param>
|
||||
void DisplayPageNavigation(ref int currentPage, int arraySize, int itemsPerPage)
|
||||
{
|
||||
Rect pagePos = EditorGUILayout.GetControlRect(false, 20);
|
||||
pagePos.width /= 3;
|
||||
|
||||
int shiftMultiplier = Event.current.shift ? 10 : 1; // Page + Shift goes 10 page forward
|
||||
|
||||
// Previous Page
|
||||
GUI.enabled = currentPage > 0;
|
||||
|
||||
if (GUI.Button(pagePos, "Previous Page"))
|
||||
{
|
||||
currentPage -= 1 * shiftMultiplier;
|
||||
//m_isNewPage = true;
|
||||
}
|
||||
|
||||
// Page Counter
|
||||
GUI.enabled = true;
|
||||
pagePos.x += pagePos.width;
|
||||
int totalPages = (int)(arraySize / (float)itemsPerPage + 0.999f);
|
||||
GUI.Label(pagePos, "Page " + (currentPage + 1) + " / " + totalPages, TMP_UIStyleManager.centeredLabel);
|
||||
|
||||
// Next Page
|
||||
pagePos.x += pagePos.width;
|
||||
GUI.enabled = itemsPerPage * (currentPage + 1) < arraySize;
|
||||
|
||||
if (GUI.Button(pagePos, "Next Page"))
|
||||
{
|
||||
currentPage += 1 * shiftMultiplier;
|
||||
//m_isNewPage = true;
|
||||
}
|
||||
|
||||
// Clamp page range
|
||||
currentPage = Mathf.Clamp(currentPage, 0, arraySize / itemsPerPage);
|
||||
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Method to update the properties of all sprites
|
||||
/// </summary>
|
||||
/// <param name="property"></param>
|
||||
/// <param name="value"></param>
|
||||
void UpdateGlobalProperty(string property, float value)
|
||||
{
|
||||
int arraySize = m_SpriteGlyphTableProperty.arraySize;
|
||||
|
||||
for (int i = 0; i < arraySize; i++)
|
||||
{
|
||||
// Get a reference to the sprite glyph.
|
||||
SerializedProperty spriteGlyphProperty = m_SpriteGlyphTableProperty.GetArrayElementAtIndex(i);
|
||||
|
||||
if (property == "m_Scale")
|
||||
{
|
||||
spriteGlyphProperty.FindPropertyRelative(property).floatValue = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
SerializedProperty glyphMetricsProperty = spriteGlyphProperty.FindPropertyRelative("m_Metrics");
|
||||
glyphMetricsProperty.FindPropertyRelative(property).floatValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
GUI.changed = false;
|
||||
}
|
||||
|
||||
// Check if any of the Style elements were clicked on.
|
||||
private 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;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Swap the sprite item at the currently selected array index to another index.
|
||||
/// </summary>
|
||||
/// <param name="selectedIndex">Selected index.</param>
|
||||
/// <param name="newIndex">New index.</param>
|
||||
void SwapCharacterElements(int selectedIndex, int newIndex)
|
||||
{
|
||||
m_SpriteCharacterTableProperty.MoveArrayElement(selectedIndex, newIndex);
|
||||
m_selectedElement = newIndex;
|
||||
m_IsCharacterSearchDirty = true;
|
||||
m_SpriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move Sprite Element at selected index to another index and reorder sprite list.
|
||||
/// </summary>
|
||||
/// <param name="selectedIndex"></param>
|
||||
/// <param name="newIndex"></param>
|
||||
void MoveCharacterToIndex(int selectedIndex, int newIndex)
|
||||
{
|
||||
int arraySize = m_SpriteCharacterTableProperty.arraySize;
|
||||
|
||||
if (newIndex >= arraySize)
|
||||
newIndex = arraySize - 1;
|
||||
|
||||
m_SpriteCharacterTableProperty.MoveArrayElement(selectedIndex, newIndex);
|
||||
|
||||
m_selectedElement = newIndex;
|
||||
m_IsCharacterSearchDirty = true;
|
||||
m_SpriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
|
||||
|
||||
// TODO: Need to handle switching pages if the character or glyph is moved to a different page.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="selectedIndex"></param>
|
||||
/// <param name="newIndex"></param>
|
||||
void SwapGlyphElements(int selectedIndex, int newIndex)
|
||||
{
|
||||
m_SpriteGlyphTableProperty.MoveArrayElement(selectedIndex, newIndex);
|
||||
m_selectedElement = newIndex;
|
||||
m_IsGlyphSearchDirty = true;
|
||||
m_SpriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move Sprite Element at selected index to another index and reorder sprite list.
|
||||
/// </summary>
|
||||
/// <param name="selectedIndex"></param>
|
||||
/// <param name="newIndex"></param>
|
||||
void MoveGlyphToIndex(int selectedIndex, int newIndex)
|
||||
{
|
||||
int arraySize = m_SpriteGlyphTableProperty.arraySize;
|
||||
|
||||
if (newIndex >= arraySize)
|
||||
newIndex = arraySize - 1;
|
||||
|
||||
m_SpriteGlyphTableProperty.MoveArrayElement(selectedIndex, newIndex);
|
||||
|
||||
m_selectedElement = newIndex;
|
||||
m_IsGlyphSearchDirty = true;
|
||||
m_SpriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
|
||||
|
||||
// TODO: Need to handle switching pages if the character or glyph is moved to a different page.
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="target"></param>
|
||||
void CopyCharacterSerializedProperty(SerializedProperty source, ref SerializedProperty target)
|
||||
{
|
||||
target.FindPropertyRelative("m_Name").stringValue = source.FindPropertyRelative("m_Name").stringValue;
|
||||
target.FindPropertyRelative("m_HashCode").intValue = source.FindPropertyRelative("m_HashCode").intValue;
|
||||
target.FindPropertyRelative("m_Unicode").intValue = source.FindPropertyRelative("m_Unicode").intValue;
|
||||
target.FindPropertyRelative("m_GlyphIndex").intValue = source.FindPropertyRelative("m_GlyphIndex").intValue;
|
||||
target.FindPropertyRelative("m_Scale").floatValue = source.FindPropertyRelative("m_Scale").floatValue;
|
||||
}
|
||||
|
||||
void CopyGlyphSerializedProperty(SerializedProperty srcGlyph, ref SerializedProperty dstGlyph)
|
||||
{
|
||||
// TODO : Should make a generic function which copies each of the properties.
|
||||
|
||||
// Index
|
||||
dstGlyph.FindPropertyRelative("m_Index").intValue = srcGlyph.FindPropertyRelative("m_Index").intValue;
|
||||
|
||||
// GlyphMetrics
|
||||
SerializedProperty srcGlyphMetrics = srcGlyph.FindPropertyRelative("m_Metrics");
|
||||
SerializedProperty dstGlyphMetrics = dstGlyph.FindPropertyRelative("m_Metrics");
|
||||
|
||||
dstGlyphMetrics.FindPropertyRelative("m_Width").floatValue = srcGlyphMetrics.FindPropertyRelative("m_Width").floatValue;
|
||||
dstGlyphMetrics.FindPropertyRelative("m_Height").floatValue = srcGlyphMetrics.FindPropertyRelative("m_Height").floatValue;
|
||||
dstGlyphMetrics.FindPropertyRelative("m_HorizontalBearingX").floatValue = srcGlyphMetrics.FindPropertyRelative("m_HorizontalBearingX").floatValue;
|
||||
dstGlyphMetrics.FindPropertyRelative("m_HorizontalBearingY").floatValue = srcGlyphMetrics.FindPropertyRelative("m_HorizontalBearingY").floatValue;
|
||||
dstGlyphMetrics.FindPropertyRelative("m_HorizontalAdvance").floatValue = srcGlyphMetrics.FindPropertyRelative("m_HorizontalAdvance").floatValue;
|
||||
|
||||
// GlyphRect
|
||||
SerializedProperty srcGlyphRect = srcGlyph.FindPropertyRelative("m_GlyphRect");
|
||||
SerializedProperty dstGlyphRect = dstGlyph.FindPropertyRelative("m_GlyphRect");
|
||||
|
||||
dstGlyphRect.FindPropertyRelative("m_X").intValue = srcGlyphRect.FindPropertyRelative("m_X").intValue;
|
||||
dstGlyphRect.FindPropertyRelative("m_Y").intValue = srcGlyphRect.FindPropertyRelative("m_Y").intValue;
|
||||
dstGlyphRect.FindPropertyRelative("m_Width").intValue = srcGlyphRect.FindPropertyRelative("m_Width").intValue;
|
||||
dstGlyphRect.FindPropertyRelative("m_Height").intValue = srcGlyphRect.FindPropertyRelative("m_Height").intValue;
|
||||
|
||||
dstGlyph.FindPropertyRelative("m_Scale").floatValue = srcGlyph.FindPropertyRelative("m_Scale").floatValue;
|
||||
dstGlyph.FindPropertyRelative("m_AtlasIndex").intValue = srcGlyph.FindPropertyRelative("m_AtlasIndex").intValue;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="searchPattern"></param>
|
||||
/// <returns></returns>
|
||||
void SearchCharacterTable(string searchPattern, ref List<int> searchResults)
|
||||
{
|
||||
if (searchResults == null) searchResults = new List<int>();
|
||||
searchResults.Clear();
|
||||
|
||||
int arraySize = m_SpriteCharacterTableProperty.arraySize;
|
||||
|
||||
for (int i = 0; i < arraySize; i++)
|
||||
{
|
||||
SerializedProperty sourceSprite = m_SpriteCharacterTableProperty.GetArrayElementAtIndex(i);
|
||||
|
||||
// Check for potential match against array index
|
||||
if (i.ToString().Contains(searchPattern))
|
||||
{
|
||||
searchResults.Add(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for potential match against decimal id
|
||||
int id = sourceSprite.FindPropertyRelative("m_GlyphIndex").intValue;
|
||||
if (id.ToString().Contains(searchPattern))
|
||||
{
|
||||
searchResults.Add(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for potential match against name
|
||||
string name = sourceSprite.FindPropertyRelative("m_Name").stringValue.ToLower(System.Globalization.CultureInfo.InvariantCulture).Trim();
|
||||
if (name.Contains(searchPattern))
|
||||
{
|
||||
searchResults.Add(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SearchGlyphTable(string searchPattern, ref List<int> searchResults)
|
||||
{
|
||||
if (searchResults == null) searchResults = new List<int>();
|
||||
searchResults.Clear();
|
||||
|
||||
int arraySize = m_SpriteGlyphTableProperty.arraySize;
|
||||
|
||||
for (int i = 0; i < arraySize; i++)
|
||||
{
|
||||
SerializedProperty sourceSprite = m_SpriteGlyphTableProperty.GetArrayElementAtIndex(i);
|
||||
|
||||
// Check for potential match against array index
|
||||
if (i.ToString().Contains(searchPattern))
|
||||
{
|
||||
searchResults.Add(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for potential match against decimal id
|
||||
int id = sourceSprite.FindPropertyRelative("m_GlyphIndex").intValue;
|
||||
if (id.ToString().Contains(searchPattern))
|
||||
{
|
||||
searchResults.Add(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for potential match against name
|
||||
string name = sourceSprite.FindPropertyRelative("m_Name").stringValue.ToLower(System.Globalization.CultureInfo.InvariantCulture).Trim();
|
||||
if (name.Contains(searchPattern))
|
||||
{
|
||||
searchResults.Add(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b09be1f217d34247af54863a2f5587e1
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,232 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using TMPro.EditorUtilities;
|
||||
using TMPro.SpriteAssetUtilities;
|
||||
|
||||
namespace TMPro
|
||||
{
|
||||
public class TMP_SpriteAssetImporter : EditorWindow
|
||||
{
|
||||
// Create Sprite Asset Editor Window
|
||||
[MenuItem("Window/TextMeshPro/Sprite Importer", false, 2026)]
|
||||
public static void ShowFontAtlasCreatorWindow()
|
||||
{
|
||||
var window = GetWindow<TMP_SpriteAssetImporter>();
|
||||
window.titleContent = new GUIContent("Sprite Importer");
|
||||
window.Focus();
|
||||
}
|
||||
|
||||
Texture2D m_SpriteAtlas;
|
||||
SpriteAssetImportFormats m_SpriteDataFormat = SpriteAssetImportFormats.TexturePacker;
|
||||
TextAsset m_JsonFile;
|
||||
|
||||
string m_CreationFeedback;
|
||||
|
||||
TMP_SpriteAsset m_SpriteAsset;
|
||||
List<TMP_Sprite> m_SpriteInfoList = new List<TMP_Sprite>();
|
||||
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
// Set Editor Window Size
|
||||
SetEditorWindowSize();
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
DrawEditorPanel();
|
||||
}
|
||||
|
||||
|
||||
void DrawEditorPanel()
|
||||
{
|
||||
// label
|
||||
GUILayout.Label("Import Settings", EditorStyles.boldLabel);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
// Sprite Texture Selection
|
||||
m_JsonFile = EditorGUILayout.ObjectField("Sprite Data Source", m_JsonFile, typeof(TextAsset), false) as TextAsset;
|
||||
|
||||
m_SpriteDataFormat = (SpriteAssetImportFormats)EditorGUILayout.EnumPopup("Import Format", m_SpriteDataFormat);
|
||||
|
||||
// Sprite Texture Selection
|
||||
m_SpriteAtlas = EditorGUILayout.ObjectField("Sprite Texture Atlas", m_SpriteAtlas, typeof(Texture2D), false) as Texture2D;
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
m_CreationFeedback = string.Empty;
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
GUI.enabled = m_JsonFile != null && m_SpriteAtlas != null && m_SpriteDataFormat == SpriteAssetImportFormats.TexturePacker;
|
||||
|
||||
// Create Sprite Asset
|
||||
if (GUILayout.Button("Create Sprite Asset"))
|
||||
{
|
||||
m_CreationFeedback = string.Empty;
|
||||
|
||||
// Read json data file
|
||||
if (m_JsonFile != null && m_SpriteDataFormat == SpriteAssetImportFormats.TexturePacker)
|
||||
{
|
||||
TexturePacker.SpriteDataObject sprites = JsonUtility.FromJson<TexturePacker.SpriteDataObject>(m_JsonFile.text);
|
||||
|
||||
if (sprites != null && sprites.frames != null && sprites.frames.Count > 0)
|
||||
{
|
||||
int spriteCount = sprites.frames.Count;
|
||||
|
||||
// Update import results
|
||||
m_CreationFeedback = "<b>Import Results</b>\n--------------------\n";
|
||||
m_CreationFeedback += "<color=#C0ffff><b>" + spriteCount + "</b></color> Sprites were imported from file.";
|
||||
|
||||
// Create sprite info list
|
||||
m_SpriteInfoList = CreateSpriteInfoList(sprites);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GUI.enabled = true;
|
||||
|
||||
// Creation Feedback
|
||||
GUILayout.Space(5);
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.Height(60));
|
||||
{
|
||||
EditorGUILayout.LabelField(m_CreationFeedback, TMP_UIStyleManager.label);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.Space(5);
|
||||
GUI.enabled = m_JsonFile != null && m_SpriteAtlas && m_SpriteInfoList != null && m_SpriteInfoList.Count > 0; // Enable Save Button if font_Atlas is not Null.
|
||||
if (GUILayout.Button("Save Sprite Asset") && m_JsonFile != null)
|
||||
{
|
||||
string filePath = EditorUtility.SaveFilePanel("Save Sprite Asset File", new FileInfo(AssetDatabase.GetAssetPath(m_JsonFile)).DirectoryName, m_JsonFile.name, "asset");
|
||||
|
||||
if (filePath.Length == 0)
|
||||
return;
|
||||
|
||||
SaveSpriteAsset(filePath);
|
||||
}
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
List<TMP_Sprite> CreateSpriteInfoList(TexturePacker.SpriteDataObject spriteDataObject)
|
||||
{
|
||||
List<TexturePacker.SpriteData> importedSprites = spriteDataObject.frames;
|
||||
|
||||
List<TMP_Sprite> spriteInfoList = new List<TMP_Sprite>();
|
||||
|
||||
for (int i = 0; i < importedSprites.Count; i++)
|
||||
{
|
||||
TMP_Sprite sprite = new TMP_Sprite();
|
||||
|
||||
sprite.id = i;
|
||||
sprite.name = Path.GetFileNameWithoutExtension(importedSprites[i].filename) ?? "";
|
||||
sprite.hashCode = TMP_TextUtilities.GetSimpleHashCode(sprite.name);
|
||||
|
||||
// Attempt to extract Unicode value from name
|
||||
int unicode;
|
||||
int indexOfSeperator = sprite.name.IndexOf('-');
|
||||
if (indexOfSeperator != -1)
|
||||
unicode = TMP_TextUtilities.StringHexToInt(sprite.name.Substring(indexOfSeperator + 1));
|
||||
else
|
||||
unicode = TMP_TextUtilities.StringHexToInt(sprite.name);
|
||||
|
||||
sprite.unicode = unicode;
|
||||
|
||||
sprite.x = importedSprites[i].frame.x;
|
||||
sprite.y = m_SpriteAtlas.height - (importedSprites[i].frame.y + importedSprites[i].frame.h);
|
||||
sprite.width = importedSprites[i].frame.w;
|
||||
sprite.height = importedSprites[i].frame.h;
|
||||
|
||||
//Calculate sprite pivot position
|
||||
sprite.pivot = importedSprites[i].pivot;
|
||||
|
||||
// Properties the can be modified
|
||||
sprite.xAdvance = sprite.width;
|
||||
sprite.scale = 1.0f;
|
||||
sprite.xOffset = 0 - (sprite.width * sprite.pivot.x);
|
||||
sprite.yOffset = sprite.height - (sprite.height * sprite.pivot.y);
|
||||
|
||||
spriteInfoList.Add(sprite);
|
||||
}
|
||||
|
||||
return spriteInfoList;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
void SaveSpriteAsset(string filePath)
|
||||
{
|
||||
filePath = filePath.Substring(0, filePath.Length - 6); // Trim file extension from filePath.
|
||||
|
||||
string dataPath = Application.dataPath;
|
||||
|
||||
if (filePath.IndexOf(dataPath, System.StringComparison.InvariantCultureIgnoreCase) == -1)
|
||||
{
|
||||
Debug.LogError("You're saving the font asset in a directory outside of this project folder. This is not supported. Please select a directory under \"" + dataPath + "\"");
|
||||
return;
|
||||
}
|
||||
|
||||
string relativeAssetPath = filePath.Substring(dataPath.Length - 6);
|
||||
string dirName = Path.GetDirectoryName(relativeAssetPath);
|
||||
string fileName = Path.GetFileNameWithoutExtension(relativeAssetPath);
|
||||
string pathNoExt = dirName + "/" + fileName;
|
||||
|
||||
|
||||
// Create new Sprite Asset using this texture
|
||||
m_SpriteAsset = CreateInstance<TMP_SpriteAsset>();
|
||||
AssetDatabase.CreateAsset(m_SpriteAsset, pathNoExt + ".asset");
|
||||
|
||||
// Compute the hash code for the sprite asset.
|
||||
m_SpriteAsset.hashCode = TMP_TextUtilities.GetSimpleHashCode(m_SpriteAsset.name);
|
||||
|
||||
// Assign new Sprite Sheet texture to the Sprite Asset.
|
||||
m_SpriteAsset.spriteSheet = m_SpriteAtlas;
|
||||
m_SpriteAsset.spriteInfoList = m_SpriteInfoList;
|
||||
|
||||
// Add new default material for sprite asset.
|
||||
AddDefaultMaterial(m_SpriteAsset);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create and add new default material to sprite asset.
|
||||
/// </summary>
|
||||
/// <param name="spriteAsset"></param>
|
||||
static void AddDefaultMaterial(TMP_SpriteAsset spriteAsset)
|
||||
{
|
||||
Shader shader = Shader.Find("TextMeshPro/Sprite");
|
||||
Material material = new Material(shader);
|
||||
material.SetTexture(ShaderUtilities.ID_MainTex, spriteAsset.spriteSheet);
|
||||
|
||||
spriteAsset.material = material;
|
||||
material.hideFlags = HideFlags.HideInHierarchy;
|
||||
AssetDatabase.AddObjectToAsset(material, spriteAsset);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Limits the minimum size of the editor window.
|
||||
/// </summary>
|
||||
void SetEditorWindowSize()
|
||||
{
|
||||
EditorWindow editorWindow = this;
|
||||
|
||||
Vector2 currentWindowSize = editorWindow.minSize;
|
||||
|
||||
editorWindow.minSize = new Vector2(Mathf.Max(230, currentWindowSize.x), Mathf.Max(300, currentWindowSize.y));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1ea944dcf8849ebab391e461b99ccb7
|
||||
timeCreated: 1480023525
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,329 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.TextCore;
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
public static class TMP_SpriteAssetMenu
|
||||
{
|
||||
// Add a Context Menu to the Sprite Asset Editor Panel to Create and Add a Default Material.
|
||||
[MenuItem("CONTEXT/TMP_SpriteAsset/Add Default Material", false, 2200)]
|
||||
static void CopyTexture(MenuCommand command)
|
||||
{
|
||||
TMP_SpriteAsset spriteAsset = (TMP_SpriteAsset)command.context;
|
||||
|
||||
// Make sure the sprite asset already contains a default material
|
||||
if (spriteAsset != null && spriteAsset.material == null)
|
||||
{
|
||||
// Add new default material for sprite asset.
|
||||
AddDefaultMaterial(spriteAsset);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a Context Menu to the Sprite Asset Editor Panel to update existing sprite assets.
|
||||
[MenuItem("CONTEXT/TMP_SpriteAsset/Update Sprite Asset", false, 2100)]
|
||||
static void UpdateSpriteAsset(MenuCommand command)
|
||||
{
|
||||
TMP_SpriteAsset spriteAsset = (TMP_SpriteAsset)command.context;
|
||||
|
||||
if (spriteAsset == null)
|
||||
return;
|
||||
|
||||
// Get a list of all the sprites contained in the texture referenced by the sprite asset.
|
||||
// This only works if the texture is set to sprite mode.
|
||||
string filePath = AssetDatabase.GetAssetPath(spriteAsset.spriteSheet);
|
||||
|
||||
if (string.IsNullOrEmpty(filePath))
|
||||
return;
|
||||
|
||||
// Get all the Sprites sorted Left to Right / Top to Bottom
|
||||
Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(filePath).Select(x => x as Sprite).Where(x => x != null).OrderByDescending(x => x.rect.y).ThenBy(x => x.rect.x).ToArray();
|
||||
|
||||
List<TMP_SpriteGlyph> spriteGlyphTable = spriteAsset.spriteGlyphTable;
|
||||
|
||||
// Finding available glyph indexes to insert new glyphs into.
|
||||
var tempGlyphTable = spriteGlyphTable.OrderBy(glyph => glyph.index).ToList();
|
||||
List<uint> availableGlyphIndexes = new List<uint>();
|
||||
|
||||
int elementIndex = 0;
|
||||
for (uint i = 0; i < tempGlyphTable[tempGlyphTable.Count - 1].index; i++)
|
||||
{
|
||||
uint currentElementIndex = tempGlyphTable[elementIndex].index;
|
||||
|
||||
if (i == currentElementIndex)
|
||||
elementIndex += 1;
|
||||
else
|
||||
availableGlyphIndexes.Add(i);
|
||||
}
|
||||
|
||||
// Iterate over each of the sprites in the texture to try to match them to existing sprites in the sprite asset.
|
||||
for (int i = 0; i < sprites.Length; i++)
|
||||
{
|
||||
int id = sprites[i].GetInstanceID();
|
||||
|
||||
int glyphIndex = spriteGlyphTable.FindIndex(item => item.sprite.GetInstanceID() == id);
|
||||
|
||||
if (glyphIndex == -1)
|
||||
{
|
||||
// Add new Sprite Glyph to the table
|
||||
Sprite sprite = sprites[i];
|
||||
|
||||
TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph();
|
||||
|
||||
// Get available glyph index
|
||||
if (availableGlyphIndexes.Count > 0)
|
||||
{
|
||||
spriteGlyph.index = availableGlyphIndexes[0];
|
||||
availableGlyphIndexes.RemoveAt(0);
|
||||
}
|
||||
else
|
||||
spriteGlyph.index = (uint)spriteGlyphTable.Count;
|
||||
|
||||
spriteGlyph.metrics = new GlyphMetrics(sprite.rect.width, sprite.rect.height, -sprite.pivot.x, sprite.rect.height - sprite.pivot.y, sprite.rect.width);
|
||||
spriteGlyph.glyphRect = new GlyphRect(sprite.rect);
|
||||
spriteGlyph.scale = 1.0f;
|
||||
spriteGlyph.sprite = sprite;
|
||||
|
||||
spriteGlyphTable.Add(spriteGlyph);
|
||||
|
||||
TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(0, spriteGlyph);
|
||||
spriteCharacter.name = sprite.name;
|
||||
spriteCharacter.scale = 1.0f;
|
||||
|
||||
spriteAsset.spriteCharacterTable.Add(spriteCharacter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look for changes in existing Sprite Glyph
|
||||
Sprite sprite = sprites[i];
|
||||
|
||||
TMP_SpriteGlyph spriteGlyph = spriteGlyphTable[glyphIndex];
|
||||
|
||||
// We only update changes to the sprite position / glyph rect.
|
||||
if (spriteGlyph.glyphRect.x != sprite.rect.x || spriteGlyph.glyphRect.y != sprite.rect.y || spriteGlyph.glyphRect.width != sprite.rect.width || spriteGlyph.glyphRect.height != sprite.rect.height)
|
||||
spriteGlyph.glyphRect = new GlyphRect(sprite.rect);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort glyph table by glyph index
|
||||
spriteAsset.SortGlyphTable();
|
||||
spriteAsset.UpdateLookupTables();
|
||||
TMPro_EventManager.ON_SPRITE_ASSET_PROPERTY_CHANGED(true, spriteAsset);
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("Assets/Create/TextMeshPro/Sprite Asset", false, 110)]
|
||||
public static void CreateSpriteAsset()
|
||||
{
|
||||
Object target = Selection.activeObject;
|
||||
|
||||
// Make sure the selection is a texture.
|
||||
if (target == null || target.GetType() != typeof(Texture2D))
|
||||
{
|
||||
Debug.LogWarning("A texture which contains sprites must first be selected in order to create a TextMesh Pro Sprite Asset.");
|
||||
return;
|
||||
}
|
||||
|
||||
Texture2D sourceTex = target as Texture2D;
|
||||
|
||||
// Get the path to the selected texture.
|
||||
string filePathWithName = AssetDatabase.GetAssetPath(sourceTex);
|
||||
string fileNameWithExtension = Path.GetFileName(filePathWithName);
|
||||
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePathWithName);
|
||||
string filePath = filePathWithName.Replace(fileNameWithExtension, "");
|
||||
|
||||
// Check if Sprite Asset already exists
|
||||
TMP_SpriteAsset spriteAsset = AssetDatabase.LoadAssetAtPath(filePath + fileNameWithoutExtension + ".asset", typeof(TMP_SpriteAsset)) as TMP_SpriteAsset;
|
||||
bool isNewAsset = spriteAsset == null ? true : false;
|
||||
|
||||
if (isNewAsset)
|
||||
{
|
||||
// Create new Sprite Asset using this texture
|
||||
spriteAsset = ScriptableObject.CreateInstance<TMP_SpriteAsset>();
|
||||
AssetDatabase.CreateAsset(spriteAsset, filePath + fileNameWithoutExtension + ".asset");
|
||||
|
||||
spriteAsset.version = "1.1.0";
|
||||
|
||||
// Compute the hash code for the sprite asset.
|
||||
spriteAsset.hashCode = TMP_TextUtilities.GetSimpleHashCode(spriteAsset.name);
|
||||
|
||||
// Assign new Sprite Sheet texture to the Sprite Asset.
|
||||
spriteAsset.spriteSheet = sourceTex;
|
||||
|
||||
List<TMP_SpriteGlyph> spriteGlyphTable = new List<TMP_SpriteGlyph>();
|
||||
List<TMP_SpriteCharacter> spriteCharacterTable = new List<TMP_SpriteCharacter>();
|
||||
|
||||
PopulateSpriteTables(sourceTex, ref spriteCharacterTable, ref spriteGlyphTable);
|
||||
|
||||
spriteAsset.spriteCharacterTable = spriteCharacterTable;
|
||||
spriteAsset.spriteGlyphTable = spriteGlyphTable;
|
||||
|
||||
// Add new default material for sprite asset.
|
||||
AddDefaultMaterial(spriteAsset);
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// spriteAsset.spriteInfoList = UpdateSpriteInfo(spriteAsset);
|
||||
|
||||
// // Make sure the sprite asset already contains a default material
|
||||
// if (spriteAsset.material == null)
|
||||
// {
|
||||
// // Add new default material for sprite asset.
|
||||
// AddDefaultMaterial(spriteAsset);
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
// Update Lookup tables.
|
||||
spriteAsset.UpdateLookupTables();
|
||||
|
||||
// Get the Sprites contained in the Sprite Sheet
|
||||
EditorUtility.SetDirty(spriteAsset);
|
||||
|
||||
//spriteAsset.sprites = sprites;
|
||||
|
||||
// Set source texture back to Not Readable.
|
||||
//texImporter.isReadable = false;
|
||||
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(spriteAsset)); // Re-import font asset to get the new updated version.
|
||||
|
||||
//AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
|
||||
private static void PopulateSpriteTables(Texture source, ref List<TMP_SpriteCharacter> spriteCharacterTable, ref List<TMP_SpriteGlyph> spriteGlyphTable)
|
||||
{
|
||||
//Debug.Log("Creating new Sprite Asset.");
|
||||
|
||||
string filePath = AssetDatabase.GetAssetPath(source);
|
||||
|
||||
// Get all the Sprites sorted by Index
|
||||
Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(filePath).Select(x => x as Sprite).Where(x => x != null).OrderByDescending(x => x.rect.y).ThenBy(x => x.rect.x).ToArray();
|
||||
|
||||
for (int i = 0; i < sprites.Length; i++)
|
||||
{
|
||||
Sprite sprite = sprites[i];
|
||||
|
||||
TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph();
|
||||
spriteGlyph.index = (uint)i;
|
||||
spriteGlyph.metrics = new GlyphMetrics(sprite.rect.width, sprite.rect.height, -sprite.pivot.x, sprite.rect.height - sprite.pivot.y, sprite.rect.width);
|
||||
spriteGlyph.glyphRect = new GlyphRect(sprite.rect);
|
||||
spriteGlyph.scale = 1.0f;
|
||||
spriteGlyph.sprite = sprite;
|
||||
|
||||
spriteGlyphTable.Add(spriteGlyph);
|
||||
|
||||
TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter(0, spriteGlyph);
|
||||
spriteCharacter.name = sprite.name;
|
||||
spriteCharacter.scale = 1.0f;
|
||||
|
||||
spriteCharacterTable.Add(spriteCharacter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create and add new default material to sprite asset.
|
||||
/// </summary>
|
||||
/// <param name="spriteAsset"></param>
|
||||
private static void AddDefaultMaterial(TMP_SpriteAsset spriteAsset)
|
||||
{
|
||||
Shader shader = Shader.Find("TextMeshPro/Sprite");
|
||||
Material material = new Material(shader);
|
||||
material.SetTexture(ShaderUtilities.ID_MainTex, spriteAsset.spriteSheet);
|
||||
|
||||
spriteAsset.material = material;
|
||||
material.hideFlags = HideFlags.HideInHierarchy;
|
||||
AssetDatabase.AddObjectToAsset(material, spriteAsset);
|
||||
}
|
||||
|
||||
|
||||
// Update existing SpriteInfo
|
||||
private static List<TMP_Sprite> UpdateSpriteInfo(TMP_SpriteAsset spriteAsset)
|
||||
{
|
||||
//Debug.Log("Updating Sprite Asset.");
|
||||
|
||||
string filePath = AssetDatabase.GetAssetPath(spriteAsset.spriteSheet);
|
||||
|
||||
// Get all the Sprites sorted Left to Right / Top to Bottom
|
||||
Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(filePath).Select(x => x as Sprite).Where(x => x != null).OrderByDescending(x => x.rect.y).ThenBy(x => x.rect.x).ToArray();
|
||||
|
||||
for (int i = 0; i < sprites.Length; i++)
|
||||
{
|
||||
Sprite sprite = sprites[i];
|
||||
|
||||
// Check if the sprite is already contained in the SpriteInfoList
|
||||
int index = -1;
|
||||
if (spriteAsset.spriteInfoList.Count > i && spriteAsset.spriteInfoList[i].sprite != null)
|
||||
index = spriteAsset.spriteInfoList.FindIndex(item => item.sprite.GetInstanceID() == sprite.GetInstanceID());
|
||||
|
||||
// Use existing SpriteInfo if it already exists
|
||||
TMP_Sprite spriteInfo = index == -1 ? new TMP_Sprite() : spriteAsset.spriteInfoList[index];
|
||||
|
||||
Rect spriteRect = sprite.rect;
|
||||
spriteInfo.x = spriteRect.x;
|
||||
spriteInfo.y = spriteRect.y;
|
||||
spriteInfo.width = spriteRect.width;
|
||||
spriteInfo.height = spriteRect.height;
|
||||
|
||||
// Get Sprite Pivot
|
||||
Vector2 pivot = new Vector2(0 - (sprite.bounds.min.x) / (sprite.bounds.extents.x * 2), 0 - (sprite.bounds.min.y) / (sprite.bounds.extents.y * 2));
|
||||
|
||||
// The position of the pivot influences the Offset position.
|
||||
spriteInfo.pivot = new Vector2(0 - pivot.x * spriteRect.width, spriteRect.height - pivot.y * spriteRect.height);
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
// Find the next available index for this Sprite
|
||||
int[] ids = spriteAsset.spriteInfoList.Select(item => item.id).ToArray();
|
||||
|
||||
int id = 0;
|
||||
for (int j = 0; j < ids.Length; j++ )
|
||||
{
|
||||
if (ids[0] != 0) break;
|
||||
|
||||
if (j > 0 && (ids[j] - ids[j - 1]) > 1)
|
||||
{
|
||||
id = ids[j - 1] + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
id = j + 1;
|
||||
}
|
||||
|
||||
spriteInfo.sprite = sprite;
|
||||
spriteInfo.name = sprite.name;
|
||||
spriteInfo.hashCode = TMP_TextUtilities.GetSimpleHashCode(spriteInfo.name);
|
||||
spriteInfo.id = id;
|
||||
spriteInfo.xAdvance = spriteRect.width;
|
||||
spriteInfo.scale = 1.0f;
|
||||
|
||||
spriteInfo.xOffset = spriteInfo.pivot.x;
|
||||
spriteInfo.yOffset = spriteInfo.pivot.y;
|
||||
|
||||
spriteAsset.spriteInfoList.Add(spriteInfo);
|
||||
|
||||
// Sort the Sprites by ID
|
||||
spriteAsset.spriteInfoList = spriteAsset.spriteInfoList.OrderBy(s => s.id).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
spriteAsset.spriteInfoList[index] = spriteInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return spriteAsset.spriteInfoList;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1048a87135154606808bf2030da32d18
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,225 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.TextCore;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
[CustomPropertyDrawer(typeof(TMP_SpriteCharacter))]
|
||||
public class TMP_SpriteCharacterPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
int m_GlyphSelectedForEditing = -1;
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
SerializedProperty prop_SpriteName = property.FindPropertyRelative("m_Name");
|
||||
SerializedProperty prop_SpriteNameHashCode = property.FindPropertyRelative("m_HashCode");
|
||||
SerializedProperty prop_SpriteUnicode = property.FindPropertyRelative("m_Unicode");
|
||||
SerializedProperty prop_SpriteGlyphIndex = property.FindPropertyRelative("m_GlyphIndex");
|
||||
SerializedProperty prop_SpriteScale = property.FindPropertyRelative("m_Scale");
|
||||
|
||||
|
||||
GUIStyle style = new GUIStyle(EditorStyles.label);
|
||||
style.richText = true;
|
||||
|
||||
EditorGUIUtility.labelWidth = 40f;
|
||||
EditorGUIUtility.fieldWidth = 50;
|
||||
|
||||
Rect rect = new Rect(position.x + 60, position.y, position.width, 49);
|
||||
|
||||
// Display non-editable fields
|
||||
if (GUI.enabled == false)
|
||||
{
|
||||
// Sprite Character Index
|
||||
int.TryParse(property.displayName.Split(' ')[1], out int spriteCharacterIndex);
|
||||
EditorGUI.LabelField(new Rect(rect.x, rect.y, 75f, 18), new GUIContent("Index: <color=#FFFF80>" + spriteCharacterIndex + "</color>"), style);
|
||||
|
||||
EditorGUI.LabelField(new Rect(rect.x + 75f, rect.y, 120f, 18), new GUIContent("Unicode: <color=#FFFF80>0x" + prop_SpriteUnicode.intValue.ToString("X") + "</color>"), style);
|
||||
EditorGUI.LabelField(new Rect(rect.x + 195f, rect.y, rect.width - 255, 18), new GUIContent("Name: <color=#FFFF80>" + prop_SpriteName.stringValue + "</color>"), style);
|
||||
|
||||
EditorGUI.LabelField(new Rect(rect.x, rect.y + 18, 120, 18), new GUIContent("Glyph ID: <color=#FFFF80>" + prop_SpriteGlyphIndex.intValue + "</color>"), style);
|
||||
|
||||
// Draw Sprite Glyph (if exists)
|
||||
DrawSpriteGlyph(position, property);
|
||||
|
||||
EditorGUI.LabelField(new Rect(rect.x, rect.y + 36, 80, 18), new GUIContent("Scale: <color=#FFFF80>" + prop_SpriteScale.floatValue + "</color>"), style);
|
||||
}
|
||||
else // Display editable fields
|
||||
{
|
||||
// Get a reference to the underlying Sprite Asset
|
||||
TMP_SpriteAsset spriteAsset = property.serializedObject.targetObject as TMP_SpriteAsset;
|
||||
|
||||
// Sprite Character Index
|
||||
int.TryParse(property.displayName.Split(' ')[1], out int spriteCharacterIndex);
|
||||
|
||||
EditorGUI.LabelField(new Rect(rect.x, rect.y, 75f, 18), new GUIContent("Index: <color=#FFFF80>" + spriteCharacterIndex + "</color>"), style);
|
||||
|
||||
EditorGUIUtility.labelWidth = 55f;
|
||||
GUI.SetNextControlName("Unicode Input");
|
||||
EditorGUI.BeginChangeCheck();
|
||||
string unicode = EditorGUI.DelayedTextField(new Rect(rect.x + 75f, rect.y, 120, 18), "Unicode:", prop_SpriteUnicode.intValue.ToString("X"));
|
||||
|
||||
if (GUI.GetNameOfFocusedControl() == "Unicode Input")
|
||||
{
|
||||
//Filter out unwanted characters.
|
||||
char chr = Event.current.character;
|
||||
if ((chr < '0' || chr > '9') && (chr < 'a' || chr > 'f') && (chr < 'A' || chr > 'F'))
|
||||
{
|
||||
Event.current.character = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
// Update Unicode value
|
||||
prop_SpriteUnicode.intValue = TMP_TextUtilities.StringHexToInt(unicode);
|
||||
spriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
|
||||
}
|
||||
|
||||
EditorGUIUtility.labelWidth = 41f;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.DelayedTextField(new Rect(rect.x + 195f, rect.y, rect.width - 255, 18), prop_SpriteName, new GUIContent("Name:"));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
// Recompute hashCode for new name
|
||||
prop_SpriteNameHashCode.intValue = TMP_TextUtilities.GetSimpleHashCode(prop_SpriteName.stringValue);
|
||||
spriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
|
||||
}
|
||||
|
||||
EditorGUIUtility.labelWidth = 59f;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.DelayedIntField(new Rect(rect.x, rect.y + 18, 100, 18), prop_SpriteGlyphIndex, new GUIContent("Glyph ID:"));
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
spriteAsset.m_IsSpriteAssetLookupTablesDirty = true;
|
||||
}
|
||||
|
||||
// Draw Sprite Glyph (if exists)
|
||||
DrawSpriteGlyph(position, property);
|
||||
|
||||
int glyphIndex = prop_SpriteGlyphIndex.intValue;
|
||||
|
||||
// Reset glyph selection if new character has been selected.
|
||||
if (GUI.enabled && m_GlyphSelectedForEditing != glyphIndex)
|
||||
m_GlyphSelectedForEditing = -1;
|
||||
|
||||
// Display button to edit the glyph data.
|
||||
if (GUI.Button(new Rect(rect.x + 120, rect.y + 18, 75, 18), new GUIContent("Edit Glyph")))
|
||||
{
|
||||
if (m_GlyphSelectedForEditing == -1)
|
||||
m_GlyphSelectedForEditing = glyphIndex;
|
||||
else
|
||||
m_GlyphSelectedForEditing = -1;
|
||||
|
||||
// Button clicks should not result in potential change.
|
||||
GUI.changed = false;
|
||||
}
|
||||
|
||||
// Show the glyph property drawer if selected
|
||||
if (glyphIndex == m_GlyphSelectedForEditing && GUI.enabled)
|
||||
{
|
||||
if (spriteAsset != null)
|
||||
{
|
||||
// Lookup glyph and draw glyph (if available)
|
||||
int elementIndex = spriteAsset.spriteGlyphTable.FindIndex(item => item.index == glyphIndex);
|
||||
|
||||
if (elementIndex != -1)
|
||||
{
|
||||
// Get a reference to the Sprite Glyph Table
|
||||
SerializedProperty prop_SpriteGlyphTable = property.serializedObject.FindProperty("m_SpriteGlyphTable");
|
||||
|
||||
SerializedProperty prop_SpriteGlyph = prop_SpriteGlyphTable.GetArrayElementAtIndex(elementIndex);
|
||||
SerializedProperty prop_GlyphMetrics = prop_SpriteGlyph.FindPropertyRelative("m_Metrics");
|
||||
SerializedProperty prop_GlyphRect = prop_SpriteGlyph.FindPropertyRelative("m_GlyphRect");
|
||||
|
||||
Rect newRect = EditorGUILayout.GetControlRect(false, 115);
|
||||
EditorGUI.DrawRect(new Rect(newRect.x + 62, newRect.y - 20, newRect.width - 62, newRect.height - 5), new Color(0.1f, 0.1f, 0.1f, 0.45f));
|
||||
EditorGUI.DrawRect(new Rect(newRect.x + 63, newRect.y - 19, newRect.width - 64, newRect.height - 7), new Color(0.3f, 0.3f, 0.3f, 0.8f));
|
||||
|
||||
// Display GlyphRect
|
||||
newRect.x += 65;
|
||||
newRect.y -= 18;
|
||||
newRect.width += 5;
|
||||
EditorGUI.PropertyField(newRect, prop_GlyphRect);
|
||||
|
||||
// Display GlyphMetrics
|
||||
newRect.y += 45;
|
||||
EditorGUI.PropertyField(newRect, prop_GlyphMetrics);
|
||||
|
||||
rect.y += 120;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUIUtility.labelWidth = 39f;
|
||||
EditorGUI.PropertyField(new Rect(rect.x, rect.y + 36, 80, 18), prop_SpriteScale, new GUIContent("Scale:"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return 58;
|
||||
}
|
||||
|
||||
|
||||
void DrawSpriteGlyph(Rect position, SerializedProperty property)
|
||||
{
|
||||
// Get a reference to the sprite glyph table
|
||||
TMP_SpriteAsset spriteAsset = property.serializedObject.targetObject as TMP_SpriteAsset;
|
||||
|
||||
if (spriteAsset == null)
|
||||
return;
|
||||
|
||||
int glyphIndex = property.FindPropertyRelative("m_GlyphIndex").intValue;
|
||||
|
||||
// Lookup glyph and draw glyph (if available)
|
||||
int elementIndex = spriteAsset.spriteGlyphTable.FindIndex(item => item.index == glyphIndex);
|
||||
|
||||
if (elementIndex != -1)
|
||||
{
|
||||
// Get a reference to the Sprite Glyph Table
|
||||
SerializedProperty prop_SpriteGlyphTable = property.serializedObject.FindProperty("m_SpriteGlyphTable");
|
||||
SerializedProperty prop_SpriteGlyph = prop_SpriteGlyphTable.GetArrayElementAtIndex(elementIndex);
|
||||
SerializedProperty prop_GlyphRect = prop_SpriteGlyph.FindPropertyRelative("m_GlyphRect");
|
||||
|
||||
// Get a reference to the sprite texture
|
||||
Texture tex = spriteAsset.spriteSheet;
|
||||
|
||||
// Return if we don't have a texture assigned to the sprite asset.
|
||||
if (tex == null)
|
||||
{
|
||||
Debug.LogWarning("Please assign a valid Sprite Atlas texture to the [" + spriteAsset.name + "] Sprite Asset.", spriteAsset);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 spriteTexPosition = new Vector2(position.x, position.y);
|
||||
Vector2 spriteSize = new Vector2(48, 48);
|
||||
Vector2 alignmentOffset = new Vector2((58 - spriteSize.x) / 2, (58 - spriteSize.y) / 2);
|
||||
|
||||
float x = prop_GlyphRect.FindPropertyRelative("m_X").intValue;
|
||||
float y = prop_GlyphRect.FindPropertyRelative("m_Y").intValue;
|
||||
float spriteWidth = prop_GlyphRect.FindPropertyRelative("m_Width").intValue;
|
||||
float spriteHeight = prop_GlyphRect.FindPropertyRelative("m_Height").intValue;
|
||||
|
||||
if (spriteWidth >= spriteHeight)
|
||||
{
|
||||
spriteSize.y = spriteHeight * spriteSize.x / spriteWidth;
|
||||
spriteTexPosition.y += (spriteSize.x - spriteSize.y) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
spriteSize.x = spriteWidth * spriteSize.y / spriteHeight;
|
||||
spriteTexPosition.x += (spriteSize.y - spriteSize.x) / 2;
|
||||
}
|
||||
|
||||
// Compute the normalized texture coordinates
|
||||
Rect texCoords = new Rect(x / tex.width, y / tex.height, spriteWidth / tex.width, spriteHeight / tex.height);
|
||||
GUI.DrawTextureWithTexCoords(new Rect(spriteTexPosition.x + alignmentOffset.x, spriteTexPosition.y + alignmentOffset.y, spriteSize.x, spriteSize.y), tex, texCoords, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37cff9f5a86ae494c8cb04423580480d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,93 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.TextCore;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
[CustomPropertyDrawer(typeof(TMP_SpriteGlyph))]
|
||||
public class TMP_SpriteGlyphPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
SerializedProperty prop_GlyphIndex = property.FindPropertyRelative("m_Index");
|
||||
SerializedProperty prop_GlyphMetrics = property.FindPropertyRelative("m_Metrics");
|
||||
SerializedProperty prop_GlyphRect = property.FindPropertyRelative("m_GlyphRect");
|
||||
SerializedProperty prop_Scale = property.FindPropertyRelative("m_Scale");
|
||||
SerializedProperty prop_AtlasIndex = property.FindPropertyRelative("m_AtlasIndex");
|
||||
|
||||
GUIStyle style = new GUIStyle(EditorStyles.label);
|
||||
style.richText = true;
|
||||
|
||||
Rect rect = new Rect(position.x + 70, position.y, position.width, 49);
|
||||
|
||||
// Draw GlyphRect
|
||||
EditorGUI.PropertyField(rect, prop_GlyphRect);
|
||||
|
||||
// Draw GlyphMetrics
|
||||
rect.y += 45;
|
||||
EditorGUI.PropertyField(rect, prop_GlyphMetrics);
|
||||
|
||||
EditorGUIUtility.labelWidth = 40f;
|
||||
EditorGUI.PropertyField(new Rect(rect.x, rect.y + 65, 75, 18), prop_Scale, new GUIContent("Scale:"));
|
||||
|
||||
EditorGUIUtility.labelWidth = 74f;
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 85, rect.y + 65, 95, 18), prop_AtlasIndex, new GUIContent("Atlas Index:"));
|
||||
|
||||
DrawGlyph(position, property);
|
||||
|
||||
int.TryParse(property.displayName.Split(' ')[1], out int spriteCharacterIndex);
|
||||
float labelWidthIndex = GUI.skin.label.CalcSize(new GUIContent("#" + spriteCharacterIndex)).x;
|
||||
EditorGUI.LabelField(new Rect(position.x, position.y + 5, 64f, 18f), new GUIContent("#" + spriteCharacterIndex), style);
|
||||
|
||||
float labelWidthID = GUI.skin.label.CalcSize(new GUIContent("ID: " + prop_GlyphIndex.intValue)).x;
|
||||
EditorGUI.LabelField(new Rect(position.x + (64 - labelWidthID) / 2, position.y + 110, 64f, 18f), new GUIContent("ID: <color=#FFFF80>" + prop_GlyphIndex.intValue + "</color>"), style);
|
||||
}
|
||||
|
||||
void DrawGlyph(Rect position, SerializedProperty property)
|
||||
{
|
||||
// Get a reference to the sprite texture
|
||||
Texture tex = (property.serializedObject.targetObject as TMP_SpriteAsset).spriteSheet;
|
||||
|
||||
// Return if we don't have a texture assigned to the sprite asset.
|
||||
if (tex == null)
|
||||
{
|
||||
Debug.LogWarning("Please assign a valid Sprite Atlas texture to the [" + property.serializedObject.targetObject.name + "] Sprite Asset.", property.serializedObject.targetObject);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 spriteTexPosition = new Vector2(position.x, position.y);
|
||||
Vector2 spriteSize = new Vector2(65, 65);
|
||||
|
||||
SerializedProperty prop_GlyphRect = property.FindPropertyRelative("m_GlyphRect");
|
||||
|
||||
int spriteImageX = prop_GlyphRect.FindPropertyRelative("m_X").intValue;
|
||||
int spriteImageY = prop_GlyphRect.FindPropertyRelative("m_Y").intValue;
|
||||
int spriteImageWidth = prop_GlyphRect.FindPropertyRelative("m_Width").intValue;
|
||||
int spriteImageHeight = prop_GlyphRect.FindPropertyRelative("m_Height").intValue;
|
||||
|
||||
if (spriteImageWidth >= spriteImageHeight)
|
||||
{
|
||||
spriteSize.y = spriteImageHeight * spriteSize.x / spriteImageWidth;
|
||||
spriteTexPosition.y += (spriteSize.x - spriteSize.y) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
spriteSize.x = spriteImageWidth * spriteSize.y / spriteImageHeight;
|
||||
spriteTexPosition.x += (spriteSize.y - spriteSize.x) / 2;
|
||||
}
|
||||
|
||||
// Compute the normalized texture coordinates
|
||||
Rect texCoords = new Rect((float)spriteImageX / tex.width, (float)spriteImageY / tex.height, (float)spriteImageWidth / tex.width, (float)spriteImageHeight / tex.height);
|
||||
GUI.DrawTextureWithTexCoords(new Rect(spriteTexPosition.x + 5, spriteTexPosition.y + 32f, spriteSize.x, spriteSize.y), tex, texCoords, true);
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return 130f;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 056819c66570ca54cadb72330a354050
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,49 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
public static class TMP_StyleAssetMenu
|
||||
{
|
||||
|
||||
[MenuItem("Assets/Create/TextMeshPro/Style Sheet", false, 120)]
|
||||
public static void CreateTextMeshProObjectPerform()
|
||||
{
|
||||
string filePath;
|
||||
if (Selection.assetGUIDs.Length == 0)
|
||||
{
|
||||
// No asset selected.
|
||||
filePath = "Assets";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the path of the selected folder or asset.
|
||||
filePath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);
|
||||
|
||||
// Get the file extension of the selected asset as it might need to be removed.
|
||||
string fileExtension = Path.GetExtension(filePath);
|
||||
if (fileExtension != "")
|
||||
{
|
||||
filePath = Path.GetDirectoryName(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string filePathWithName = AssetDatabase.GenerateUniqueAssetPath(filePath + "/TMP StyleSheet.asset");
|
||||
|
||||
//// Create new Style Sheet Asset.
|
||||
TMP_StyleSheet styleSheet = ScriptableObject.CreateInstance<TMP_StyleSheet>();
|
||||
|
||||
AssetDatabase.CreateAsset(styleSheet, filePathWithName);
|
||||
|
||||
EditorUtility.SetDirty(styleSheet);
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23a562f2cac6401f9f91251c68a1a794
|
||||
timeCreated: 1432690168
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,278 @@
|
||||
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 = 90;
|
||||
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.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(108, 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(108, 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
|
||||
{
|
||||
|
||||
SerializedProperty m_StyleListProp;
|
||||
|
||||
int m_SelectedElement = -1;
|
||||
|
||||
//private Event m_CurrentEvent;
|
||||
int m_Page;
|
||||
|
||||
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_StyleListProp = serializedObject.FindProperty("m_StyleList");
|
||||
}
|
||||
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
Event currentEvent = Event.current;
|
||||
|
||||
serializedObject.Update();
|
||||
|
||||
int arraySize = m_StyleListProp.arraySize;
|
||||
int itemsPerPage = (Screen.height - 178) / 111;
|
||||
|
||||
if (arraySize > 0)
|
||||
{
|
||||
// Display each Style entry using the StyleDrawer PropertyDrawer.
|
||||
for (int i = itemsPerPage * m_Page; i < arraySize && 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 spriteInfo = m_StyleListProp.GetArrayElementAtIndex(i);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(spriteInfo);
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int shiftMultiplier = currentEvent.shift ? 10 : 1; // Page + Shift goes 10 page forward
|
||||
|
||||
GUILayout.Space(-3f);
|
||||
|
||||
Rect pagePos = EditorGUILayout.GetControlRect(false, 20);
|
||||
pagePos.width /= 6;
|
||||
|
||||
// Return if we can't display any items.
|
||||
if (itemsPerPage == 0) return;
|
||||
|
||||
|
||||
// Add new style.
|
||||
pagePos.x += pagePos.width * 4;
|
||||
if (GUI.Button(pagePos, "+"))
|
||||
{
|
||||
m_StyleListProp.arraySize += 1;
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
TMP_StyleSheet.RefreshStyles();
|
||||
}
|
||||
|
||||
|
||||
// Delete selected style.
|
||||
pagePos.x += pagePos.width;
|
||||
if (m_SelectedElement == -1) GUI.enabled = false;
|
||||
if (GUI.Button(pagePos, "-"))
|
||||
{
|
||||
if (m_SelectedElement != -1)
|
||||
m_StyleListProp.DeleteArrayElementAtIndex(m_SelectedElement);
|
||||
|
||||
m_SelectedElement = -1;
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
TMP_StyleSheet.RefreshStyles();
|
||||
}
|
||||
|
||||
GUILayout.Space(5f);
|
||||
|
||||
pagePos = EditorGUILayout.GetControlRect(false, 20);
|
||||
pagePos.width /= 3;
|
||||
|
||||
|
||||
// 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;
|
||||
int totalPages = (int)(arraySize / (float)itemsPerPage + 0.999f);
|
||||
GUI.Label(pagePos, "Page " + (m_Page + 1) + " / " + totalPages, TMP_UIStyleManager.centeredLabel);
|
||||
|
||||
// Next Page
|
||||
pagePos.x += pagePos.width;
|
||||
if (itemsPerPage * (m_Page + 1) < arraySize) 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, arraySize / itemsPerPage);
|
||||
|
||||
|
||||
if (serializedObject.ApplyModifiedProperties())
|
||||
TMPro_EventManager.ON_TEXT_STYLE_PROPERTY_CHANGED(true);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34e2c9b9d9e44953933afe37461f44e6
|
||||
timeCreated: 1432683777
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,98 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
[CustomEditor(typeof(TMP_SubMeshUI)), CanEditMultipleObjects]
|
||||
public class TMP_SubMeshUI_Editor : Editor
|
||||
{
|
||||
private struct m_foldout
|
||||
{ // Track Inspector foldout panel states, globally.
|
||||
//public static bool textInput = true;
|
||||
public static bool fontSettings = true;
|
||||
//public static bool extraSettings = false;
|
||||
//public static bool shadowSetting = false;
|
||||
//public static bool materialEditor = true;
|
||||
}
|
||||
|
||||
private SerializedProperty fontAsset_prop;
|
||||
private SerializedProperty spriteAsset_prop;
|
||||
|
||||
private TMP_SubMeshUI m_SubMeshComponent;
|
||||
|
||||
private CanvasRenderer m_canvasRenderer;
|
||||
private Editor m_materialEditor;
|
||||
private Material m_targetMaterial;
|
||||
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
fontAsset_prop = serializedObject.FindProperty("m_fontAsset");
|
||||
spriteAsset_prop = serializedObject.FindProperty("m_spriteAsset");
|
||||
|
||||
m_SubMeshComponent = target as TMP_SubMeshUI;
|
||||
//m_rectTransform = m_SubMeshComponent.rectTransform;
|
||||
m_canvasRenderer = m_SubMeshComponent.canvasRenderer;
|
||||
|
||||
|
||||
// Create new Material Editor if one does not exists
|
||||
if (m_canvasRenderer != null && m_canvasRenderer.GetMaterial() != null)
|
||||
{
|
||||
m_materialEditor = Editor.CreateEditor(m_canvasRenderer.GetMaterial());
|
||||
m_targetMaterial = m_canvasRenderer.GetMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void OnDisable()
|
||||
{
|
||||
// Destroy material editor if one exists
|
||||
if (m_materialEditor != null)
|
||||
{
|
||||
//Debug.Log("Destroying Inline Material Editor.");
|
||||
DestroyImmediate(m_materialEditor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
GUI.enabled = false;
|
||||
EditorGUILayout.PropertyField(fontAsset_prop);
|
||||
EditorGUILayout.PropertyField(spriteAsset_prop);
|
||||
GUI.enabled = true;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// If a Custom Material Editor exists, we use it.
|
||||
if (m_canvasRenderer != null && m_canvasRenderer.GetMaterial() != null)
|
||||
{
|
||||
Material mat = m_canvasRenderer.GetMaterial();
|
||||
|
||||
//Debug.Log(mat + " " + m_targetMaterial);
|
||||
|
||||
if (mat != m_targetMaterial)
|
||||
{
|
||||
// Destroy previous Material Instance
|
||||
//Debug.Log("New Material has been assigned.");
|
||||
m_targetMaterial = mat;
|
||||
DestroyImmediate(m_materialEditor);
|
||||
}
|
||||
|
||||
|
||||
if (m_materialEditor == null)
|
||||
{
|
||||
m_materialEditor = Editor.CreateEditor(mat);
|
||||
}
|
||||
|
||||
m_materialEditor.DrawHeader();
|
||||
|
||||
|
||||
m_materialEditor.OnInspectorGUI();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b01141ed8f74d198965c86f25eb7040
|
||||
timeCreated: 1452757501
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,76 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
[CustomEditor(typeof(TMP_SubMesh)), CanEditMultipleObjects]
|
||||
public class TMP_SubMesh_Editor : Editor
|
||||
{
|
||||
private struct m_foldout
|
||||
{ // Track Inspector foldout panel states, globally.
|
||||
//public static bool textInput = true;
|
||||
public static bool fontSettings = true;
|
||||
//public static bool extraSettings = false;
|
||||
//public static bool shadowSetting = false;
|
||||
//public static bool materialEditor = true;
|
||||
}
|
||||
|
||||
private SerializedProperty fontAsset_prop;
|
||||
private SerializedProperty spriteAsset_prop;
|
||||
|
||||
private TMP_SubMesh m_SubMeshComponent;
|
||||
private Renderer m_Renderer;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
fontAsset_prop = serializedObject.FindProperty("m_fontAsset");
|
||||
spriteAsset_prop = serializedObject.FindProperty("m_spriteAsset");
|
||||
|
||||
m_SubMeshComponent = target as TMP_SubMesh;
|
||||
|
||||
m_Renderer = m_SubMeshComponent.renderer;
|
||||
}
|
||||
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
EditorGUI.indentLevel = 0;
|
||||
|
||||
GUI.enabled = false;
|
||||
EditorGUILayout.PropertyField(fontAsset_prop);
|
||||
EditorGUILayout.PropertyField(spriteAsset_prop);
|
||||
GUI.enabled = true;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
// SORTING LAYERS
|
||||
var sortingLayerNames = SortingLayerHelper.sortingLayerNames;
|
||||
|
||||
// Look up the layer name using the current layer ID
|
||||
string oldName = SortingLayerHelper.GetSortingLayerNameFromID(m_Renderer.sortingLayerID);
|
||||
|
||||
// Use the name to look up our array index into the names list
|
||||
int oldLayerIndex = System.Array.IndexOf(sortingLayerNames, oldName);
|
||||
|
||||
// Show the pop-up for the names
|
||||
int newLayerIndex = EditorGUILayout.Popup("Sorting Layer", oldLayerIndex, sortingLayerNames);
|
||||
|
||||
// If the index changes, look up the ID for the new index to store as the new ID
|
||||
if (newLayerIndex != oldLayerIndex)
|
||||
{
|
||||
//Undo.RecordObject(renderer, "Edit Sorting Layer");
|
||||
m_Renderer.sortingLayerID = SortingLayerHelper.GetSortingLayerIDForIndex(newLayerIndex);
|
||||
//EditorUtility.SetDirty(renderer);
|
||||
}
|
||||
|
||||
// Expose the manual sorting order
|
||||
int newSortingLayerOrder = EditorGUILayout.IntField("Order in Layer", m_Renderer.sortingOrder);
|
||||
if (newSortingLayerOrder != m_Renderer.sortingOrder)
|
||||
{
|
||||
//Undo.RecordObject(renderer, "Edit Sorting Order");
|
||||
m_Renderer.sortingOrder = newSortingLayerOrder;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd2fe74169b54bf58fca17288513ef38
|
||||
timeCreated: 1456189048
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,119 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
[CustomPropertyDrawer(typeof(TextAlignmentOptions))]
|
||||
public class TMP_TextAlignmentDrawer : PropertyDrawer
|
||||
{
|
||||
const int k_AlignmentButtonWidth = 24;
|
||||
const int k_AlignmentButtonHeight = 20;
|
||||
const int k_WideViewWidth = 504;
|
||||
const int k_ControlsSpacing = 6;
|
||||
const int k_GroupWidth = k_AlignmentButtonWidth * 6;
|
||||
static readonly int k_TextAlignmentHash = "DoTextAligmentControl".GetHashCode();
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return EditorGUIUtility.currentViewWidth > k_WideViewWidth ? k_AlignmentButtonHeight : k_AlignmentButtonHeight * 2 + 3;
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
var id = GUIUtility.GetControlID(k_TextAlignmentHash, FocusType.Keyboard, position);
|
||||
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
{
|
||||
var controlArea = EditorGUI.PrefixLabel(position, id, label);
|
||||
|
||||
var horizontalAligment = new Rect(controlArea.x, controlArea.y, k_GroupWidth, k_AlignmentButtonHeight);
|
||||
var verticalAligment = new Rect(!(EditorGUIUtility.currentViewWidth > k_WideViewWidth) ? controlArea.x : horizontalAligment.xMax + k_ControlsSpacing, !(EditorGUIUtility.currentViewWidth > k_WideViewWidth) ? controlArea.y + k_AlignmentButtonHeight + 3 : controlArea.y, k_GroupWidth, k_AlignmentButtonHeight);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
var selectedHorizontal = DoHorizontalAligmentControl(horizontalAligment, property);
|
||||
var selectedVertical = DoVerticalAligmentControl(verticalAligment, property);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
var value = (0x1 << selectedHorizontal) | (0x100 << selectedVertical);
|
||||
property.intValue = value;
|
||||
}
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
static int DoHorizontalAligmentControl(Rect position, SerializedProperty alignment)
|
||||
{
|
||||
var selected = TMP_EditorUtility.GetHorizontalAlignmentGridValue(alignment.intValue);
|
||||
|
||||
var values = new bool[6];
|
||||
|
||||
values[selected] = true;
|
||||
|
||||
if (alignment.hasMultipleDifferentValues)
|
||||
{
|
||||
foreach (var obj in alignment.serializedObject.targetObjects)
|
||||
{
|
||||
var text = obj as TMP_Text;
|
||||
if (text != null)
|
||||
{
|
||||
values[TMP_EditorUtility.GetHorizontalAlignmentGridValue((int)text.alignment)] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
position.width = k_AlignmentButtonWidth;
|
||||
|
||||
for (var i = 0; i < values.Length; i++)
|
||||
{
|
||||
var oldValue = values[i];
|
||||
var newValue = TMP_EditorUtility.EditorToggle(position, oldValue, TMP_UIStyleManager.alignContentA[i], i == 0 ? TMP_UIStyleManager.alignmentButtonLeft : (i == 5 ? TMP_UIStyleManager.alignmentButtonRight : TMP_UIStyleManager.alignmentButtonMid));
|
||||
if (newValue != oldValue)
|
||||
{
|
||||
selected = i;
|
||||
}
|
||||
position.x += position.width;
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
static int DoVerticalAligmentControl(Rect position, SerializedProperty alignment)
|
||||
{
|
||||
var selected = TMP_EditorUtility.GetVerticalAlignmentGridValue(alignment.intValue);
|
||||
|
||||
var values = new bool[6];
|
||||
|
||||
values[selected] = true;
|
||||
|
||||
if (alignment.hasMultipleDifferentValues)
|
||||
{
|
||||
foreach (var obj in alignment.serializedObject.targetObjects)
|
||||
{
|
||||
var text = obj as TMP_Text;
|
||||
if (text != null)
|
||||
{
|
||||
values[TMP_EditorUtility.GetVerticalAlignmentGridValue((int)text.alignment)] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
position.width = k_AlignmentButtonWidth;
|
||||
|
||||
for (var i = 0; i < values.Length; i++)
|
||||
{
|
||||
var oldValue = values[i];
|
||||
var newValue = TMP_EditorUtility.EditorToggle(position, oldValue, TMP_UIStyleManager.alignContentB[i], i == 0 ? TMP_UIStyleManager.alignmentButtonLeft : (i == 5 ? TMP_UIStyleManager.alignmentButtonRight : TMP_UIStyleManager.alignmentButtonMid));
|
||||
if (newValue != oldValue)
|
||||
{
|
||||
selected = i;
|
||||
}
|
||||
position.x += position.width;
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c55a64c7570474f47a94abe39ebfef04
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,134 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
public static class TMP_UIStyleManager
|
||||
{
|
||||
public static GUIStyle label;
|
||||
public static GUIStyle textAreaBoxWindow;
|
||||
public static GUIStyle boldFoldout;
|
||||
public static GUIStyle panelTitle;
|
||||
public static GUIStyle sectionHeader;
|
||||
public static GUIStyle centeredLabel;
|
||||
public static GUIStyle rightLabel;
|
||||
public static GUIStyle wrappingTextArea;
|
||||
|
||||
public static GUIStyle alignmentButtonLeft;
|
||||
public static GUIStyle alignmentButtonMid;
|
||||
public static GUIStyle alignmentButtonRight;
|
||||
|
||||
// Alignment Button Textures
|
||||
public static Texture2D alignLeft;
|
||||
public static Texture2D alignCenter;
|
||||
public static Texture2D alignRight;
|
||||
public static Texture2D alignJustified;
|
||||
public static Texture2D alignFlush;
|
||||
public static Texture2D alignGeoCenter;
|
||||
public static Texture2D alignTop;
|
||||
public static Texture2D alignMiddle;
|
||||
public static Texture2D alignBottom;
|
||||
public static Texture2D alignBaseline;
|
||||
public static Texture2D alignMidline;
|
||||
public static Texture2D alignCapline;
|
||||
public static Texture2D sectionHeaderTexture;
|
||||
|
||||
public static GUIContent[] alignContentA;
|
||||
public static GUIContent[] alignContentB;
|
||||
|
||||
static TMP_UIStyleManager()
|
||||
{
|
||||
// Find to location of the TextMesh Pro Asset Folder (as users may have moved it)
|
||||
var tmproAssetFolderPath = TMP_EditorUtility.packageRelativePath;
|
||||
|
||||
if (EditorGUIUtility.isProSkin)
|
||||
{
|
||||
alignLeft = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignLeft.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignCenter = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignCenter.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignRight = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignRight.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignJustified = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignJustified.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignFlush = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignFlush.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignGeoCenter = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignCenterGeo.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignTop = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignTop.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignMiddle = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignMiddle.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignBottom = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignBottom.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignBaseline = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignBaseLine.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignMidline = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignMidLine.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignCapline = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignCapLine.psd", typeof(Texture2D)) as Texture2D;
|
||||
sectionHeaderTexture = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/SectionHeader_Dark.psd", typeof(Texture2D)) as Texture2D;
|
||||
}
|
||||
else
|
||||
{
|
||||
alignLeft = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignLeft_Light.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignCenter = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignCenter_Light.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignRight = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignRight_Light.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignJustified = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignJustified_Light.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignFlush = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignFlush_Light.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignGeoCenter = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignCenterGeo_Light.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignTop = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignTop_Light.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignMiddle = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignMiddle_Light.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignBottom = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignBottom_Light.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignBaseline = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignBaseLine_Light.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignMidline = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignMidLine_Light.psd", typeof(Texture2D)) as Texture2D;
|
||||
alignCapline = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/btn_AlignCapLine_Light.psd", typeof(Texture2D)) as Texture2D;
|
||||
sectionHeaderTexture = AssetDatabase.LoadAssetAtPath(tmproAssetFolderPath + "/Editor Resources/Textures/SectionHeader_Light.psd", typeof(Texture2D)) as Texture2D;
|
||||
}
|
||||
|
||||
label = new GUIStyle(EditorStyles.label) { richText = true, wordWrap = true, stretchWidth = true };
|
||||
textAreaBoxWindow = new GUIStyle(EditorStyles.textArea) { richText = true };
|
||||
boldFoldout = new GUIStyle(EditorStyles.foldout) { fontStyle = FontStyle.Bold };
|
||||
panelTitle = new GUIStyle(EditorStyles.label) { fontStyle = FontStyle.Bold };
|
||||
|
||||
sectionHeader = new GUIStyle(EditorStyles.label) { fixedHeight = 22, richText = true, border = new RectOffset(9, 9, 0, 0), overflow = new RectOffset(9, 0, 0, 0), padding = new RectOffset(0, 0, 4, 0) };
|
||||
sectionHeader.normal.background = sectionHeaderTexture;
|
||||
|
||||
centeredLabel = new GUIStyle(EditorStyles.label) { alignment = TextAnchor.MiddleCenter};
|
||||
rightLabel = new GUIStyle(EditorStyles.label) { alignment = TextAnchor.MiddleRight, richText = true };
|
||||
|
||||
|
||||
alignmentButtonLeft = new GUIStyle(EditorStyles.miniButtonLeft);
|
||||
alignmentButtonLeft.padding.left = 4;
|
||||
alignmentButtonLeft.padding.right = 4;
|
||||
alignmentButtonLeft.padding.top = 2;
|
||||
alignmentButtonLeft.padding.bottom = 2;
|
||||
|
||||
alignmentButtonMid = new GUIStyle(EditorStyles.miniButtonMid);
|
||||
alignmentButtonMid.padding.left = 4;
|
||||
alignmentButtonMid.padding.right = 4;
|
||||
alignmentButtonLeft.padding.top = 2;
|
||||
alignmentButtonLeft.padding.bottom = 2;
|
||||
|
||||
alignmentButtonRight = new GUIStyle(EditorStyles.miniButtonRight);
|
||||
alignmentButtonRight.padding.left = 4;
|
||||
alignmentButtonRight.padding.right = 4;
|
||||
alignmentButtonLeft.padding.top = 2;
|
||||
alignmentButtonLeft.padding.bottom = 2;
|
||||
|
||||
wrappingTextArea = new GUIStyle(EditorStyles.textArea);
|
||||
wrappingTextArea.wordWrap = true;
|
||||
|
||||
alignContentA = new []
|
||||
{
|
||||
new GUIContent(alignLeft, "Left"),
|
||||
new GUIContent(alignCenter, "Center"),
|
||||
new GUIContent(alignRight, "Right"),
|
||||
new GUIContent(alignJustified, "Justified"),
|
||||
new GUIContent(alignFlush, "Flush"),
|
||||
new GUIContent(alignGeoCenter, "Geometry Center")
|
||||
};
|
||||
|
||||
alignContentB = new []
|
||||
{
|
||||
new GUIContent(alignTop, "Top"),
|
||||
new GUIContent(alignMiddle, "Middle"),
|
||||
new GUIContent(alignBottom, "Bottom"),
|
||||
new GUIContent(alignBaseline, "Baseline"),
|
||||
new GUIContent(alignMidline, "Midline"),
|
||||
new GUIContent(alignCapline, "Capline")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30a939dce2fd4073955f2f20e659d506
|
||||
timeCreated: 1426454127
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,91 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
[CustomEditor(typeof(TextMeshProUGUI), true), CanEditMultipleObjects]
|
||||
public class TMP_UiEditorPanel : TMP_BaseEditorPanel
|
||||
{
|
||||
static readonly GUIContent k_RaycastTargetLabel = new GUIContent("Raycast Target", "Whether the text blocks raycasts from the Graphic Raycaster.");
|
||||
|
||||
SerializedProperty m_RaycastTargetProp;
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
m_RaycastTargetProp = serializedObject.FindProperty("m_RaycastTarget");
|
||||
}
|
||||
|
||||
protected override void DrawExtraSettings()
|
||||
{
|
||||
Foldout.extraSettings = EditorGUILayout.Foldout(Foldout.extraSettings, k_ExtraSettingsLabel, true, TMP_UIStyleManager.boldFoldout);
|
||||
if (Foldout.extraSettings)
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
|
||||
DrawMargins();
|
||||
|
||||
DrawGeometrySorting();
|
||||
|
||||
DrawRichText();
|
||||
|
||||
DrawRaycastTarget();
|
||||
|
||||
DrawParsing();
|
||||
|
||||
DrawKerning();
|
||||
|
||||
DrawPadding();
|
||||
|
||||
EditorGUI.indentLevel -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawRaycastTarget()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(m_RaycastTargetProp, k_RaycastTargetLabel);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
// Change needs to propagate to the child sub objects.
|
||||
Graphic[] graphicComponents = m_TextComponent.GetComponentsInChildren<Graphic>();
|
||||
for (int i = 1; i < graphicComponents.Length; i++)
|
||||
graphicComponents[i].raycastTarget = m_RaycastTargetProp.boolValue;
|
||||
|
||||
m_HavePropertiesChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Method to handle multi object selection
|
||||
protected override bool IsMixSelectionTypes()
|
||||
{
|
||||
GameObject[] objects = Selection.gameObjects;
|
||||
if (objects.Length > 1)
|
||||
{
|
||||
for (int i = 0; i < objects.Length; i++)
|
||||
{
|
||||
if (objects[i].GetComponent<TextMeshProUGUI>() == null)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
protected override void OnUndoRedo()
|
||||
{
|
||||
int undoEventId = Undo.GetCurrentGroup();
|
||||
int lastUndoEventId = s_EventId;
|
||||
|
||||
if (undoEventId != lastUndoEventId)
|
||||
{
|
||||
for (int i = 0; i < targets.Length; i++)
|
||||
{
|
||||
//Debug.Log("Undo & Redo Performed detected in Editor Panel. Event ID:" + Undo.GetCurrentGroup());
|
||||
TMPro_EventManager.ON_TEXTMESHPRO_UGUI_PROPERTY_CHANGED(true, targets[i] as TextMeshProUGUI);
|
||||
s_EventId = undoEventId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 21c0044a7f964773be90d197a78e4703
|
||||
timeCreated: 1443571501
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,341 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
public class TMP_ContextMenus : Editor
|
||||
{
|
||||
|
||||
private static Texture m_copiedTexture;
|
||||
|
||||
private static Material m_copiedProperties;
|
||||
private static Material m_copiedAtlasProperties;
|
||||
|
||||
|
||||
// Add a Context Menu to the Texture Editor Panel to allow Copy / Paste of Texture.
|
||||
[MenuItem("CONTEXT/Texture/Copy", false, 2000)]
|
||||
static void CopyTexture(MenuCommand command)
|
||||
{
|
||||
m_copiedTexture = command.context as Texture;
|
||||
}
|
||||
|
||||
|
||||
// Select the currently assigned material or material preset.
|
||||
[MenuItem("CONTEXT/Material/Select Material", false, 500)]
|
||||
static void SelectMaterial(MenuCommand command)
|
||||
{
|
||||
Material mat = command.context as Material;
|
||||
|
||||
// Select current material
|
||||
EditorUtility.FocusProjectWindow();
|
||||
EditorGUIUtility.PingObject(mat);
|
||||
}
|
||||
|
||||
|
||||
// Add a Context Menu to allow easy duplication of the Material.
|
||||
[MenuItem("CONTEXT/Material/Create Material Preset", false)]
|
||||
static void DuplicateMaterial(MenuCommand command)
|
||||
{
|
||||
// Get the type of text object
|
||||
// If material is not a base material, we get material leaks...
|
||||
|
||||
Material source_Mat = (Material)command.context;
|
||||
if (!EditorUtility.IsPersistent(source_Mat))
|
||||
{
|
||||
Debug.LogWarning("Material is an instance and cannot be converted into a permanent asset.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
string assetPath = AssetDatabase.GetAssetPath(source_Mat).Split('.')[0];
|
||||
|
||||
Material duplicate = new Material(source_Mat);
|
||||
|
||||
// Need to manually copy the shader keywords
|
||||
duplicate.shaderKeywords = source_Mat.shaderKeywords;
|
||||
|
||||
AssetDatabase.CreateAsset(duplicate, AssetDatabase.GenerateUniqueAssetPath(assetPath + ".mat"));
|
||||
|
||||
// Assign duplicate Material to selected object (if one is)
|
||||
if (Selection.activeGameObject != null)
|
||||
{
|
||||
TMP_Text textObject = Selection.activeGameObject.GetComponent<TMP_Text>();
|
||||
if (textObject != null)
|
||||
{
|
||||
textObject.fontSharedMaterial = duplicate;
|
||||
}
|
||||
else
|
||||
{
|
||||
TMP_SubMesh subMeshObject = Selection.activeGameObject.GetComponent<TMP_SubMesh>();
|
||||
|
||||
if (subMeshObject != null)
|
||||
subMeshObject.sharedMaterial = duplicate;
|
||||
else
|
||||
{
|
||||
TMP_SubMeshUI subMeshUIObject = Selection.activeGameObject.GetComponent<TMP_SubMeshUI>();
|
||||
|
||||
if (subMeshUIObject != null)
|
||||
subMeshUIObject.sharedMaterial = duplicate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ping newly created Material Preset.
|
||||
EditorUtility.FocusProjectWindow();
|
||||
EditorGUIUtility.PingObject(duplicate);
|
||||
}
|
||||
|
||||
|
||||
//[MenuItem("CONTEXT/MaterialComponent/Copy Material Properties", false)]
|
||||
[MenuItem("CONTEXT/Material/Copy Material Properties", false)]
|
||||
static void CopyMaterialProperties(MenuCommand command)
|
||||
{
|
||||
Material mat = null;
|
||||
if (command.context.GetType() == typeof(Material))
|
||||
mat = (Material)command.context;
|
||||
else
|
||||
{
|
||||
mat = Selection.activeGameObject.GetComponent<CanvasRenderer>().GetMaterial();
|
||||
}
|
||||
|
||||
m_copiedProperties = new Material(mat);
|
||||
|
||||
m_copiedProperties.shaderKeywords = mat.shaderKeywords;
|
||||
|
||||
m_copiedProperties.hideFlags = HideFlags.DontSave;
|
||||
}
|
||||
|
||||
|
||||
// PASTE MATERIAL
|
||||
//[MenuItem("CONTEXT/MaterialComponent/Paste Material Properties", false)]
|
||||
[MenuItem("CONTEXT/Material/Paste Material Properties", false)]
|
||||
static void PasteMaterialProperties(MenuCommand command)
|
||||
{
|
||||
|
||||
if (m_copiedProperties == null)
|
||||
{
|
||||
Debug.LogWarning("No Material Properties to Paste. Use Copy Material Properties first.");
|
||||
return;
|
||||
}
|
||||
|
||||
Material mat = null;
|
||||
if (command.context.GetType() == typeof(Material))
|
||||
mat = (Material)command.context;
|
||||
else
|
||||
{
|
||||
mat = Selection.activeGameObject.GetComponent<CanvasRenderer>().GetMaterial();
|
||||
}
|
||||
|
||||
Undo.RecordObject(mat, "Paste Material");
|
||||
|
||||
ShaderUtilities.GetShaderPropertyIDs(); // Make sure we have valid Property IDs
|
||||
if (mat.HasProperty(ShaderUtilities.ID_GradientScale))
|
||||
{
|
||||
// Preserve unique SDF properties from destination material.
|
||||
m_copiedProperties.SetTexture(ShaderUtilities.ID_MainTex, mat.GetTexture(ShaderUtilities.ID_MainTex));
|
||||
m_copiedProperties.SetFloat(ShaderUtilities.ID_GradientScale, mat.GetFloat(ShaderUtilities.ID_GradientScale));
|
||||
m_copiedProperties.SetFloat(ShaderUtilities.ID_TextureWidth, mat.GetFloat(ShaderUtilities.ID_TextureWidth));
|
||||
m_copiedProperties.SetFloat(ShaderUtilities.ID_TextureHeight, mat.GetFloat(ShaderUtilities.ID_TextureHeight));
|
||||
}
|
||||
|
||||
EditorShaderUtilities.CopyMaterialProperties(m_copiedProperties, mat);
|
||||
|
||||
// Copy ShaderKeywords from one material to the other.
|
||||
mat.shaderKeywords = m_copiedProperties.shaderKeywords;
|
||||
|
||||
// Let TextMeshPro Objects that this mat has changed.
|
||||
TMPro_EventManager.ON_MATERIAL_PROPERTY_CHANGED(true, mat);
|
||||
}
|
||||
|
||||
|
||||
// Enable Resetting of Material properties without losing unique properties of the font atlas.
|
||||
[MenuItem("CONTEXT/Material/Reset", false, 2100)]
|
||||
static void ResetSettings(MenuCommand command)
|
||||
{
|
||||
|
||||
Material mat = null;
|
||||
if (command.context.GetType() == typeof(Material))
|
||||
mat = (Material)command.context;
|
||||
else
|
||||
{
|
||||
mat = Selection.activeGameObject.GetComponent<CanvasRenderer>().GetMaterial();
|
||||
}
|
||||
|
||||
Undo.RecordObject(mat, "Reset Material");
|
||||
|
||||
ShaderUtilities.GetShaderPropertyIDs(); // Make sure we have valid Property IDs
|
||||
if (mat.HasProperty(ShaderUtilities.ID_GradientScale))
|
||||
{
|
||||
// Copy unique properties of the SDF Material
|
||||
var texture = mat.GetTexture(ShaderUtilities.ID_MainTex);
|
||||
var gradientScale = mat.GetFloat(ShaderUtilities.ID_GradientScale);
|
||||
var texWidth = mat.GetFloat(ShaderUtilities.ID_TextureWidth);
|
||||
var texHeight = mat.GetFloat(ShaderUtilities.ID_TextureHeight);
|
||||
|
||||
var stencilId = 0.0f;
|
||||
var stencilComp = 0.0f;
|
||||
|
||||
if (mat.HasProperty(ShaderUtilities.ID_StencilID))
|
||||
{
|
||||
stencilId = mat.GetFloat(ShaderUtilities.ID_StencilID);
|
||||
stencilComp = mat.GetFloat(ShaderUtilities.ID_StencilComp);
|
||||
}
|
||||
|
||||
var normalWeight = mat.GetFloat(ShaderUtilities.ID_WeightNormal);
|
||||
var boldWeight = mat.GetFloat(ShaderUtilities.ID_WeightBold);
|
||||
|
||||
// Reset the material
|
||||
Unsupported.SmartReset(mat);
|
||||
|
||||
// Reset ShaderKeywords
|
||||
mat.shaderKeywords = new string[0]; // { "BEVEL_OFF", "GLOW_OFF", "UNDERLAY_OFF" };
|
||||
|
||||
// Copy unique material properties back to the material.
|
||||
mat.SetTexture(ShaderUtilities.ID_MainTex, texture);
|
||||
mat.SetFloat(ShaderUtilities.ID_GradientScale, gradientScale);
|
||||
mat.SetFloat(ShaderUtilities.ID_TextureWidth, texWidth);
|
||||
mat.SetFloat(ShaderUtilities.ID_TextureHeight, texHeight);
|
||||
|
||||
if (mat.HasProperty(ShaderUtilities.ID_StencilID))
|
||||
{
|
||||
mat.SetFloat(ShaderUtilities.ID_StencilID, stencilId);
|
||||
mat.SetFloat(ShaderUtilities.ID_StencilComp, stencilComp);
|
||||
}
|
||||
|
||||
mat.SetFloat(ShaderUtilities.ID_WeightNormal, normalWeight);
|
||||
mat.SetFloat(ShaderUtilities.ID_WeightBold, boldWeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
Unsupported.SmartReset(mat);
|
||||
}
|
||||
|
||||
TMPro_EventManager.ON_MATERIAL_PROPERTY_CHANGED(true, mat);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//This function is used for debugging and fixing potentially broken font atlas links.
|
||||
[MenuItem("CONTEXT/Material/Copy Atlas", false, 2000)]
|
||||
static void CopyAtlas(MenuCommand command)
|
||||
{
|
||||
Material mat = command.context as Material;
|
||||
|
||||
m_copiedAtlasProperties = new Material(mat);
|
||||
m_copiedAtlasProperties.hideFlags = HideFlags.DontSave;
|
||||
}
|
||||
|
||||
|
||||
// This function is used for debugging and fixing potentially broken font atlas links
|
||||
[MenuItem("CONTEXT/Material/Paste Atlas", false, 2001)]
|
||||
static void PasteAtlas(MenuCommand command)
|
||||
{
|
||||
Material mat = command.context as Material;
|
||||
|
||||
if (m_copiedAtlasProperties != null)
|
||||
{
|
||||
Undo.RecordObject(mat, "Paste Texture");
|
||||
|
||||
ShaderUtilities.GetShaderPropertyIDs(); // Make sure we have valid Property IDs
|
||||
mat.SetTexture(ShaderUtilities.ID_MainTex, m_copiedAtlasProperties.GetTexture(ShaderUtilities.ID_MainTex));
|
||||
mat.SetFloat(ShaderUtilities.ID_GradientScale, m_copiedAtlasProperties.GetFloat(ShaderUtilities.ID_GradientScale));
|
||||
mat.SetFloat(ShaderUtilities.ID_TextureWidth, m_copiedAtlasProperties.GetFloat(ShaderUtilities.ID_TextureWidth));
|
||||
mat.SetFloat(ShaderUtilities.ID_TextureHeight, m_copiedAtlasProperties.GetFloat(ShaderUtilities.ID_TextureHeight));
|
||||
}
|
||||
else if (m_copiedTexture != null)
|
||||
{
|
||||
Undo.RecordObject(mat, "Paste Texture");
|
||||
|
||||
mat.SetTexture(ShaderUtilities.ID_MainTex, m_copiedTexture);
|
||||
}
|
||||
|
||||
//DestroyImmediate(m_copiedAtlasProperties);
|
||||
}
|
||||
|
||||
|
||||
// Context Menus for TMPro Font Assets
|
||||
//This function is used for debugging and fixing potentially broken font atlas links.
|
||||
[MenuItem("CONTEXT/TMP_FontAsset/Extract Atlas", false, 2100)]
|
||||
static void ExtractAtlas(MenuCommand command)
|
||||
{
|
||||
TMP_FontAsset font = command.context as TMP_FontAsset;
|
||||
|
||||
string fontPath = AssetDatabase.GetAssetPath(font);
|
||||
string texPath = Path.GetDirectoryName(fontPath) + "/" + Path.GetFileNameWithoutExtension(fontPath) + " Atlas.png";
|
||||
|
||||
// Create a Serialized Object of the texture to allow us to make it readable.
|
||||
SerializedObject texprop = new SerializedObject(font.material.GetTexture(ShaderUtilities.ID_MainTex));
|
||||
texprop.FindProperty("m_IsReadable").boolValue = true;
|
||||
texprop.ApplyModifiedProperties();
|
||||
|
||||
// Create a copy of the texture.
|
||||
Texture2D tex = Instantiate(font.material.GetTexture(ShaderUtilities.ID_MainTex)) as Texture2D;
|
||||
|
||||
// Set the texture to not readable again.
|
||||
texprop.FindProperty("m_IsReadable").boolValue = false;
|
||||
texprop.ApplyModifiedProperties();
|
||||
|
||||
Debug.Log(texPath);
|
||||
// Saving File for Debug
|
||||
var pngData = tex.EncodeToPNG();
|
||||
File.WriteAllBytes(texPath, pngData);
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
DestroyImmediate(tex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
[MenuItem("CONTEXT/TMP_FontAsset/Update Atlas Texture...", false, 2000)]
|
||||
static void RegenerateFontAsset(MenuCommand command)
|
||||
{
|
||||
TMP_FontAsset fontAsset = command.context as TMP_FontAsset;
|
||||
|
||||
if (fontAsset != null)
|
||||
{
|
||||
TMPro_FontAssetCreatorWindow.ShowFontAtlasCreatorWindow(fontAsset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clear Font Asset Data
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
[MenuItem("CONTEXT/TMP_FontAsset/Reset", false, 100)]
|
||||
static void ClearFontAssetData(MenuCommand command)
|
||||
{
|
||||
TMP_FontAsset fontAsset = command.context as TMP_FontAsset;
|
||||
|
||||
if (fontAsset != null && Selection.activeObject != fontAsset)
|
||||
{
|
||||
Selection.activeObject = fontAsset;
|
||||
}
|
||||
|
||||
fontAsset.ClearFontAssetData(true);
|
||||
|
||||
TMPro_EventManager.ON_FONT_PROPERTY_CHANGED(true, fontAsset);
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("CONTEXT/TrueTypeFontImporter/Create TMP Font Asset...", false, 200)]
|
||||
static void CreateFontAsset(MenuCommand command)
|
||||
{
|
||||
TrueTypeFontImporter importer = command.context as TrueTypeFontImporter;
|
||||
|
||||
if (importer != null)
|
||||
{
|
||||
Font sourceFontFile = AssetDatabase.LoadAssetAtPath<Font>(importer.assetPath);
|
||||
|
||||
if (sourceFontFile)
|
||||
TMPro_FontAssetCreatorWindow.ShowFontAtlasCreatorWindow(sourceFontFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44e1d646473a40178712cb2150f54cec
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,311 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEditor.Experimental.SceneManagement;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
public static class TMPro_CreateObjectMenu
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Create a TextMeshPro object that works with the Mesh Renderer
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
[MenuItem("GameObject/3D Object/Text - TextMeshPro", false, 30)]
|
||||
static void CreateTextMeshProObjectPerform(MenuCommand command)
|
||||
{
|
||||
GameObject go = new GameObject("Text (TMP)");
|
||||
|
||||
// Add support for new prefab mode
|
||||
StageUtility.PlaceGameObjectInCurrentStage(go);
|
||||
|
||||
TextMeshPro textMeshPro = go.AddComponent<TextMeshPro>();
|
||||
textMeshPro.text = "Sample text";
|
||||
textMeshPro.alignment = TextAlignmentOptions.TopLeft;
|
||||
|
||||
Undo.RegisterCreatedObjectUndo((Object)go, "Create " + go.name);
|
||||
|
||||
GameObject contextObject = command.context as GameObject;
|
||||
if (contextObject != null)
|
||||
{
|
||||
GameObjectUtility.SetParentAndAlign(go, contextObject);
|
||||
Undo.SetTransformParent(go.transform, contextObject.transform, "Parent " + go.name);
|
||||
}
|
||||
|
||||
Selection.activeGameObject = go;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a TextMeshPro object that works with the CanvasRenderer
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
[MenuItem("GameObject/UI/Text - TextMeshPro", false, 2001)]
|
||||
static void CreateTextMeshProGuiObjectPerform(MenuCommand menuCommand)
|
||||
{
|
||||
GameObject go = TMP_DefaultControls.CreateText(GetStandardResources());
|
||||
|
||||
// Override text color and font size
|
||||
TMP_Text textComponent = go.GetComponent<TMP_Text>();
|
||||
textComponent.color = Color.white;
|
||||
if (textComponent.m_isWaitingOnResourceLoad == false)
|
||||
textComponent.fontSize = TMP_Settings.defaultFontSize;
|
||||
|
||||
PlaceUIElementRoot(go, menuCommand);
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/UI/Button - TextMeshPro", false, 2031)]
|
||||
static public void AddButton(MenuCommand menuCommand)
|
||||
{
|
||||
GameObject go = TMP_DefaultControls.CreateButton(GetStandardResources());
|
||||
|
||||
// Override font size
|
||||
TMP_Text textComponent = go.GetComponentInChildren<TMP_Text>();
|
||||
textComponent.fontSize = 24;
|
||||
|
||||
PlaceUIElementRoot(go, menuCommand);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MenuItem("GameObject/UI/Input Field - TextMeshPro", false, 2037)]
|
||||
static void AddTextMeshProInputField(MenuCommand menuCommand)
|
||||
{
|
||||
GameObject go = TMP_DefaultControls.CreateInputField(GetStandardResources());
|
||||
PlaceUIElementRoot(go, menuCommand);
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("GameObject/UI/Dropdown - TextMeshPro", false, 2036)]
|
||||
static public void AddDropdown(MenuCommand menuCommand)
|
||||
{
|
||||
GameObject go = TMP_DefaultControls.CreateDropdown(GetStandardResources());
|
||||
PlaceUIElementRoot(go, menuCommand);
|
||||
}
|
||||
|
||||
|
||||
private const string kUILayerName = "UI";
|
||||
|
||||
private const string kStandardSpritePath = "UI/Skin/UISprite.psd";
|
||||
private const string kBackgroundSpritePath = "UI/Skin/Background.psd";
|
||||
private const string kInputFieldBackgroundPath = "UI/Skin/InputFieldBackground.psd";
|
||||
private const string kKnobPath = "UI/Skin/Knob.psd";
|
||||
private const string kCheckmarkPath = "UI/Skin/Checkmark.psd";
|
||||
private const string kDropdownArrowPath = "UI/Skin/DropdownArrow.psd";
|
||||
private const string kMaskPath = "UI/Skin/UIMask.psd";
|
||||
|
||||
static private TMP_DefaultControls.Resources s_StandardResources;
|
||||
|
||||
|
||||
static private TMP_DefaultControls.Resources GetStandardResources()
|
||||
{
|
||||
if (s_StandardResources.standard == null)
|
||||
{
|
||||
s_StandardResources.standard = AssetDatabase.GetBuiltinExtraResource<Sprite>(kStandardSpritePath);
|
||||
s_StandardResources.background = AssetDatabase.GetBuiltinExtraResource<Sprite>(kBackgroundSpritePath);
|
||||
s_StandardResources.inputField = AssetDatabase.GetBuiltinExtraResource<Sprite>(kInputFieldBackgroundPath);
|
||||
s_StandardResources.knob = AssetDatabase.GetBuiltinExtraResource<Sprite>(kKnobPath);
|
||||
s_StandardResources.checkmark = AssetDatabase.GetBuiltinExtraResource<Sprite>(kCheckmarkPath);
|
||||
s_StandardResources.dropdown = AssetDatabase.GetBuiltinExtraResource<Sprite>(kDropdownArrowPath);
|
||||
s_StandardResources.mask = AssetDatabase.GetBuiltinExtraResource<Sprite>(kMaskPath);
|
||||
}
|
||||
return s_StandardResources;
|
||||
}
|
||||
|
||||
|
||||
private static void SetPositionVisibleinSceneView(RectTransform canvasRTransform, RectTransform itemTransform)
|
||||
{
|
||||
// Find the best scene view
|
||||
SceneView sceneView = SceneView.lastActiveSceneView;
|
||||
if (sceneView == null && SceneView.sceneViews.Count > 0)
|
||||
sceneView = SceneView.sceneViews[0] as SceneView;
|
||||
|
||||
// Couldn't find a SceneView. Don't set position.
|
||||
if (sceneView == null || sceneView.camera == null)
|
||||
return;
|
||||
|
||||
// Create world space Plane from canvas position.
|
||||
Camera camera = sceneView.camera;
|
||||
Vector3 position = Vector3.zero;
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRTransform, new Vector2(camera.pixelWidth / 2, camera.pixelHeight / 2), camera, out Vector2 localPlanePosition))
|
||||
{
|
||||
// Adjust for canvas pivot
|
||||
localPlanePosition.x = localPlanePosition.x + canvasRTransform.sizeDelta.x * canvasRTransform.pivot.x;
|
||||
localPlanePosition.y = localPlanePosition.y + canvasRTransform.sizeDelta.y * canvasRTransform.pivot.y;
|
||||
|
||||
localPlanePosition.x = Mathf.Clamp(localPlanePosition.x, 0, canvasRTransform.sizeDelta.x);
|
||||
localPlanePosition.y = Mathf.Clamp(localPlanePosition.y, 0, canvasRTransform.sizeDelta.y);
|
||||
|
||||
// Adjust for anchoring
|
||||
position.x = localPlanePosition.x - canvasRTransform.sizeDelta.x * itemTransform.anchorMin.x;
|
||||
position.y = localPlanePosition.y - canvasRTransform.sizeDelta.y * itemTransform.anchorMin.y;
|
||||
|
||||
Vector3 minLocalPosition;
|
||||
minLocalPosition.x = canvasRTransform.sizeDelta.x * (0 - canvasRTransform.pivot.x) + itemTransform.sizeDelta.x * itemTransform.pivot.x;
|
||||
minLocalPosition.y = canvasRTransform.sizeDelta.y * (0 - canvasRTransform.pivot.y) + itemTransform.sizeDelta.y * itemTransform.pivot.y;
|
||||
|
||||
Vector3 maxLocalPosition;
|
||||
maxLocalPosition.x = canvasRTransform.sizeDelta.x * (1 - canvasRTransform.pivot.x) - itemTransform.sizeDelta.x * itemTransform.pivot.x;
|
||||
maxLocalPosition.y = canvasRTransform.sizeDelta.y * (1 - canvasRTransform.pivot.y) - itemTransform.sizeDelta.y * itemTransform.pivot.y;
|
||||
|
||||
position.x = Mathf.Clamp(position.x, minLocalPosition.x, maxLocalPosition.x);
|
||||
position.y = Mathf.Clamp(position.y, minLocalPosition.y, maxLocalPosition.y);
|
||||
}
|
||||
|
||||
itemTransform.anchoredPosition = position;
|
||||
itemTransform.localRotation = Quaternion.identity;
|
||||
itemTransform.localScale = Vector3.one;
|
||||
}
|
||||
|
||||
|
||||
private static void PlaceUIElementRoot(GameObject element, MenuCommand menuCommand)
|
||||
{
|
||||
GameObject parent = menuCommand.context as GameObject;
|
||||
bool explicitParentChoice = true;
|
||||
if (parent == null)
|
||||
{
|
||||
parent = GetOrCreateCanvasGameObject();
|
||||
explicitParentChoice = false;
|
||||
|
||||
// If in Prefab Mode, Canvas has to be part of Prefab contents,
|
||||
// otherwise use Prefab root instead.
|
||||
PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
|
||||
if (prefabStage != null && !prefabStage.IsPartOfPrefabContents(parent))
|
||||
parent = prefabStage.prefabContentsRoot;
|
||||
}
|
||||
if (parent.GetComponentInParent<Canvas>() == null)
|
||||
{
|
||||
// Create canvas under context GameObject,
|
||||
// and make that be the parent which UI element is added under.
|
||||
GameObject canvas = CreateNewUI();
|
||||
canvas.transform.SetParent(parent.transform, false);
|
||||
parent = canvas;
|
||||
}
|
||||
|
||||
// Setting the element to be a child of an element already in the scene should
|
||||
// be sufficient to also move the element to that scene.
|
||||
// However, it seems the element needs to be already in its destination scene when the
|
||||
// RegisterCreatedObjectUndo is performed; otherwise the scene it was created in is dirtied.
|
||||
SceneManager.MoveGameObjectToScene(element, parent.scene);
|
||||
|
||||
if (element.transform.parent == null)
|
||||
{
|
||||
Undo.SetTransformParent(element.transform, parent.transform, "Parent " + element.name);
|
||||
}
|
||||
|
||||
GameObjectUtility.EnsureUniqueNameForSibling(element);
|
||||
|
||||
// We have to fix up the undo name since the name of the object was only known after reparenting it.
|
||||
Undo.SetCurrentGroupName("Create " + element.name);
|
||||
|
||||
GameObjectUtility.SetParentAndAlign(element, parent);
|
||||
if (!explicitParentChoice) // not a context click, so center in sceneview
|
||||
SetPositionVisibleinSceneView(parent.GetComponent<RectTransform>(), element.GetComponent<RectTransform>());
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(element, "Create " + element.name);
|
||||
|
||||
Selection.activeGameObject = element;
|
||||
}
|
||||
|
||||
|
||||
static public GameObject CreateNewUI()
|
||||
{
|
||||
// Root for the UI
|
||||
var root = new GameObject("Canvas");
|
||||
root.layer = LayerMask.NameToLayer(kUILayerName);
|
||||
Canvas canvas = root.AddComponent<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
root.AddComponent<CanvasScaler>();
|
||||
root.AddComponent<GraphicRaycaster>();
|
||||
|
||||
// Works for all stages.
|
||||
StageUtility.PlaceGameObjectInCurrentStage(root);
|
||||
bool customScene = false;
|
||||
PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
|
||||
if (prefabStage != null)
|
||||
{
|
||||
root.transform.SetParent(prefabStage.prefabContentsRoot.transform, false);
|
||||
customScene = true;
|
||||
}
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(root, "Create " + root.name);
|
||||
|
||||
// If there is no event system add one...
|
||||
// No need to place event system in custom scene as these are temporary anyway.
|
||||
// It can be argued for or against placing it in the user scenes,
|
||||
// but let's not modify scene user is not currently looking at.
|
||||
if (!customScene)
|
||||
CreateEventSystem(false);
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
private static void CreateEventSystem(bool select)
|
||||
{
|
||||
CreateEventSystem(select, null);
|
||||
}
|
||||
|
||||
|
||||
private static void CreateEventSystem(bool select, GameObject parent)
|
||||
{
|
||||
var esys = Object.FindObjectOfType<EventSystem>();
|
||||
if (esys == null)
|
||||
{
|
||||
var eventSystem = new GameObject("EventSystem");
|
||||
GameObjectUtility.SetParentAndAlign(eventSystem, parent);
|
||||
esys = eventSystem.AddComponent<EventSystem>();
|
||||
eventSystem.AddComponent<StandaloneInputModule>();
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(eventSystem, "Create " + eventSystem.name);
|
||||
}
|
||||
|
||||
if (select && esys != null)
|
||||
{
|
||||
Selection.activeGameObject = esys.gameObject;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Helper function that returns a Canvas GameObject; preferably a parent of the selection, or other existing Canvas.
|
||||
static public GameObject GetOrCreateCanvasGameObject()
|
||||
{
|
||||
GameObject selectedGo = Selection.activeGameObject;
|
||||
|
||||
// Try to find a gameobject that is the selected GO or one if its parents.
|
||||
Canvas canvas = (selectedGo != null) ? selectedGo.GetComponentInParent<Canvas>() : null;
|
||||
if (IsValidCanvas(canvas))
|
||||
return canvas.gameObject;
|
||||
|
||||
// No canvas in selection or its parents? Then use any valid canvas.
|
||||
// We have to find all loaded Canvases, not just the ones in main scenes.
|
||||
Canvas[] canvasArray = StageUtility.GetCurrentStageHandle().FindComponentsOfType<Canvas>();
|
||||
for (int i = 0; i < canvasArray.Length; i++)
|
||||
if (IsValidCanvas(canvasArray[i]))
|
||||
return canvasArray[i].gameObject;
|
||||
|
||||
// No canvas in the scene at all? Then create a new one.
|
||||
return CreateNewUI();
|
||||
}
|
||||
|
||||
static bool IsValidCanvas(Canvas canvas)
|
||||
{
|
||||
if (canvas == null || !canvas.gameObject.activeInHierarchy)
|
||||
return false;
|
||||
|
||||
// It's important that the non-editable canvas from a prefab scene won't be rejected,
|
||||
// but canvases not visible in the Hierarchy at all do. Don't check for HideAndDontSave.
|
||||
if (EditorUtility.IsPersistent(canvas) || (canvas.hideFlags & HideFlags.HideInHierarchy) != 0)
|
||||
return false;
|
||||
|
||||
if (StageUtility.GetStageHandle(canvas.gameObject) != StageUtility.GetCurrentStageHandle())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7065397ff8184621aa3ca4f854491259
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,53 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
public static class EditorShaderUtilities
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Copy Shader properties from source to destination material.
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static void CopyMaterialProperties(Material source, Material destination)
|
||||
{
|
||||
MaterialProperty[] source_prop = MaterialEditor.GetMaterialProperties(new Material[] { source });
|
||||
|
||||
for (int i = 0; i < source_prop.Length; i++)
|
||||
{
|
||||
int property_ID = Shader.PropertyToID(source_prop[i].name);
|
||||
if (destination.HasProperty(property_ID))
|
||||
{
|
||||
//Debug.Log(source_prop[i].name + " Type:" + ShaderUtil.GetPropertyType(source.shader, i));
|
||||
switch (ShaderUtil.GetPropertyType(source.shader, i))
|
||||
{
|
||||
case ShaderUtil.ShaderPropertyType.Color:
|
||||
destination.SetColor(property_ID, source.GetColor(property_ID));
|
||||
break;
|
||||
case ShaderUtil.ShaderPropertyType.Float:
|
||||
destination.SetFloat(property_ID, source.GetFloat(property_ID));
|
||||
break;
|
||||
case ShaderUtil.ShaderPropertyType.Range:
|
||||
destination.SetFloat(property_ID, source.GetFloat(property_ID));
|
||||
break;
|
||||
case ShaderUtil.ShaderPropertyType.TexEnv:
|
||||
destination.SetTexture(property_ID, source.GetTexture(property_ID));
|
||||
break;
|
||||
case ShaderUtil.ShaderPropertyType.Vector:
|
||||
destination.SetVector(property_ID, source.GetVector(property_ID));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa76955fe5bb44f7915d91db8c7043c4
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 383966e89d344865a36addd5d378ffd3
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,115 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
/*
|
||||
public class TMPro_FontPlugin
|
||||
{
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
private delegate void DebugLog(string log);
|
||||
private static readonly DebugLog debugLog = DebugWrapper;
|
||||
private static readonly IntPtr functionPointer = Marshal.GetFunctionPointerForDelegate(debugLog);
|
||||
|
||||
private static void DebugWrapper(string log)
|
||||
{
|
||||
Debug.Log(log);
|
||||
}
|
||||
|
||||
public static void LinkDebugLog()
|
||||
{
|
||||
LinkDebug(functionPointer);
|
||||
}
|
||||
|
||||
[DllImport("TMPro_Plugin")]
|
||||
private static extern void LinkDebug([MarshalAs(UnmanagedType.FunctionPtr)]IntPtr debugCall);
|
||||
|
||||
[DllImport("TMPro_Plugin")]
|
||||
public static extern
|
||||
int Initialize_FontEngine();
|
||||
|
||||
[DllImport("TMPro_Plugin")]
|
||||
public static extern
|
||||
int Destroy_FontEngine();
|
||||
|
||||
[DllImport("TMPro_Plugin")]
|
||||
public static extern
|
||||
int Load_TrueType_Font(string fontPath);
|
||||
|
||||
[DllImport("TMPro_Plugin")]
|
||||
public static extern
|
||||
int FT_Size_Font(int fontSize);
|
||||
|
||||
[DllImport("TMPro_Plugin")]
|
||||
public static extern
|
||||
int Render_Character(byte[] buffer_fill, byte[] buffer_edge, int buffer_width, int buffer_height, int offset, int asc, FaceStyles style, float thickness, RenderModes rasterMode, ref FT_GlyphInfo glyphInfo);
|
||||
|
||||
[DllImport("TMPro_Plugin")]
|
||||
public static extern
|
||||
int Render_Characters(byte[] buffer, int buffer_width, int buffer_height, int character_padding, int[] asc_set, int char_count, FaceStyles style, float style_mod, bool autoSize, RenderModes renderMode, int method, ref FT_FaceInfo fontData, FT_GlyphInfo[] Output);
|
||||
|
||||
[DllImport("TMPro_Plugin")]
|
||||
public static extern
|
||||
int FT_GetKerningPairs(string fontPath, int[] characterSet, int setCount, FT_KerningPair[] kerningPairs);
|
||||
|
||||
[DllImport("TMPro_Plugin")]
|
||||
public static extern
|
||||
float Check_RenderProgress();
|
||||
|
||||
[DllImport("TMPro_Plugin")]
|
||||
internal static extern
|
||||
void SendCancellationRequest(CancellationRequestType request);
|
||||
}
|
||||
|
||||
public enum FaceStyles { Normal, Bold, Italic, Bold_Italic, Outline, Bold_Sim };
|
||||
public enum RenderModes { HintedSmooth = 0, Smooth = 1, RasterHinted = 2, Raster = 3, DistanceField16 = 6, DistanceField32 = 7 }; // SignedDistanceField64 = 8
|
||||
|
||||
internal enum CancellationRequestType : byte { None = 0x0, CancelInProgess = 0x1, WindowClosed = 0x2 };
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct FT_KerningPair
|
||||
{
|
||||
public int ascII_Left;
|
||||
public int ascII_Right;
|
||||
public float xAdvanceOffset;
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct FT_GlyphInfo
|
||||
{
|
||||
public int id;
|
||||
public float x;
|
||||
public float y;
|
||||
public float width;
|
||||
public float height;
|
||||
public float xOffset;
|
||||
public float yOffset;
|
||||
public float xAdvance;
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct FT_FaceInfo
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
|
||||
public string name;
|
||||
public int pointSize;
|
||||
public int padding;
|
||||
public float lineHeight;
|
||||
public float baseline;
|
||||
public float ascender;
|
||||
public float descender;
|
||||
public float centerLine;
|
||||
public float underline;
|
||||
public float underlineThickness;
|
||||
public int characterCount;
|
||||
public int atlasWidth;
|
||||
public int atlasHeight;
|
||||
}
|
||||
*/
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9edc9283e7d6409fab242fe8fb6a822c
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Nick Gravelyn.
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace TMPro
|
||||
{
|
||||
// Helpers used by the different sorting layer classes.
|
||||
public static class SortingLayerHelper
|
||||
{
|
||||
private static Type _utilityType;
|
||||
private static PropertyInfo _sortingLayerNamesProperty;
|
||||
private static MethodInfo _getSortingLayerUserIdMethod;
|
||||
|
||||
static SortingLayerHelper()
|
||||
{
|
||||
_utilityType = Type.GetType("UnityEditorInternal.InternalEditorUtility, UnityEditor");
|
||||
_sortingLayerNamesProperty = _utilityType.GetProperty("sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
_getSortingLayerUserIdMethod = _utilityType.GetMethod("GetSortingLayerUniqueID", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
// Gets an array of sorting layer names.
|
||||
// Since this uses reflection, callers should check for 'null' which will be returned if the reflection fails.
|
||||
public static string[] sortingLayerNames
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_sortingLayerNamesProperty == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return _sortingLayerNamesProperty.GetValue(null, null) as string[];
|
||||
}
|
||||
}
|
||||
|
||||
// Given the ID of a sorting layer, returns the sorting layer's name
|
||||
public static string GetSortingLayerNameFromID(int id)
|
||||
{
|
||||
string[] names = sortingLayerNames;
|
||||
if (names == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < names.Length; i++)
|
||||
{
|
||||
if (GetSortingLayerIDForIndex(i) == id)
|
||||
{
|
||||
return names[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Given the name of a sorting layer, returns the ID.
|
||||
public static int GetSortingLayerIDForName(string name)
|
||||
{
|
||||
string[] names = sortingLayerNames;
|
||||
if (names == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return GetSortingLayerIDForIndex(Array.IndexOf(names, name));
|
||||
}
|
||||
|
||||
// Helper to convert from a sorting layer INDEX to a sorting layer ID. These are not the same thing.
|
||||
// IDs are based on the order in which layers were created and do not change when reordering the layers.
|
||||
// Thankfully there is a private helper we can call to get the ID for a layer given its index.
|
||||
public static int GetSortingLayerIDForIndex(int index)
|
||||
{
|
||||
if (_getSortingLayerUserIdMethod == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int)_getSortingLayerUserIdMethod.Invoke(null, new object[] { index });
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88ed537c17c34f339121fe9a7d6d7a0e
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,235 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
[CustomEditor(typeof(TextContainer)), CanEditMultipleObjects]
|
||||
public class TMPro_TextContainerEditor : Editor
|
||||
{
|
||||
|
||||
// Serialized Properties
|
||||
private SerializedProperty anchorPosition_prop;
|
||||
private SerializedProperty pivot_prop;
|
||||
private SerializedProperty rectangle_prop;
|
||||
private SerializedProperty margins_prop;
|
||||
|
||||
|
||||
private TextContainer m_textContainer;
|
||||
//private Transform m_transform;
|
||||
//private Vector3[] m_Rect_handlePoints = new Vector3[4];
|
||||
//private Vector3[] m_Margin_handlePoints = new Vector3[4];
|
||||
|
||||
//private Vector2 m_anchorPosition;
|
||||
|
||||
//private Vector3 m_mousePreviousPOS;
|
||||
//private Vector2 m_previousStartPOS;
|
||||
//private int m_mouseDragFlag = 0;
|
||||
|
||||
//private static Transform m_visualHelper;
|
||||
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
|
||||
// Serialized Properties
|
||||
anchorPosition_prop = serializedObject.FindProperty("m_anchorPosition");
|
||||
pivot_prop = serializedObject.FindProperty("m_pivot");
|
||||
rectangle_prop = serializedObject.FindProperty("m_rect");
|
||||
margins_prop = serializedObject.FindProperty("m_margins");
|
||||
|
||||
m_textContainer = (TextContainer)target;
|
||||
//m_transform = m_textContainer.transform;
|
||||
|
||||
|
||||
/*
|
||||
if (m_visualHelper == null)
|
||||
{
|
||||
m_visualHelper = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
|
||||
m_visualHelper.localScale = new Vector3(0.25f, 0.25f, 0.25f);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
/*
|
||||
if (m_visualHelper != null)
|
||||
DestroyImmediate (m_visualHelper.gameObject);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(anchorPosition_prop);
|
||||
if (anchorPosition_prop.enumValueIndex == 9)
|
||||
{
|
||||
EditorGUI.indentLevel += 1;
|
||||
EditorGUILayout.PropertyField(pivot_prop, new GUIContent("Pivot Position"));
|
||||
EditorGUI.indentLevel -= 1;
|
||||
}
|
||||
|
||||
|
||||
DrawDimensionProperty(rectangle_prop, "Dimensions");
|
||||
DrawMaginProperty(margins_prop, "Margins");
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
// Re-compute pivot position when changes are made.
|
||||
if (anchorPosition_prop.enumValueIndex != 9)
|
||||
pivot_prop.vector2Value = GetAnchorPosition(anchorPosition_prop.enumValueIndex);
|
||||
|
||||
m_textContainer.hasChanged = true;
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
|
||||
private void DrawDimensionProperty(SerializedProperty property, string label)
|
||||
{
|
||||
float old_LabelWidth = EditorGUIUtility.labelWidth;
|
||||
float old_FieldWidth = EditorGUIUtility.fieldWidth;
|
||||
|
||||
Rect rect = EditorGUILayout.GetControlRect(false, 18);
|
||||
Rect pos0 = new Rect(rect.x, rect.y + 2, rect.width, 18);
|
||||
|
||||
float width = rect.width + 3;
|
||||
pos0.width = old_LabelWidth;
|
||||
GUI.Label(pos0, label);
|
||||
|
||||
Rect rectangle = property.rectValue;
|
||||
|
||||
float width_B = width - old_LabelWidth;
|
||||
float fieldWidth = width_B / 4;
|
||||
pos0.width = fieldWidth - 5;
|
||||
|
||||
pos0.x = old_LabelWidth + 15;
|
||||
GUI.Label(pos0, "Width");
|
||||
|
||||
pos0.x += fieldWidth;
|
||||
rectangle.width = EditorGUI.FloatField(pos0, GUIContent.none, rectangle.width);
|
||||
|
||||
pos0.x += fieldWidth;
|
||||
GUI.Label(pos0, "Height");
|
||||
|
||||
pos0.x += fieldWidth;
|
||||
rectangle.height = EditorGUI.FloatField(pos0, GUIContent.none, rectangle.height);
|
||||
|
||||
property.rectValue = rectangle;
|
||||
EditorGUIUtility.labelWidth = old_LabelWidth;
|
||||
EditorGUIUtility.fieldWidth = old_FieldWidth;
|
||||
}
|
||||
|
||||
|
||||
private void DrawMaginProperty(SerializedProperty property, string label)
|
||||
{
|
||||
float old_LabelWidth = EditorGUIUtility.labelWidth;
|
||||
float old_FieldWidth = EditorGUIUtility.fieldWidth;
|
||||
|
||||
Rect rect = EditorGUILayout.GetControlRect(false, 2 * 18);
|
||||
Rect pos0 = new Rect(rect.x, rect.y + 2, rect.width, 18);
|
||||
|
||||
float width = rect.width + 3;
|
||||
pos0.width = old_LabelWidth;
|
||||
GUI.Label(pos0, label);
|
||||
|
||||
//Vector4 vec = property.vector4Value;
|
||||
Vector4 vec = Vector4.zero;
|
||||
vec.x = property.FindPropertyRelative("x").floatValue;
|
||||
vec.y = property.FindPropertyRelative("y").floatValue;
|
||||
vec.z = property.FindPropertyRelative("z").floatValue;
|
||||
vec.w = property.FindPropertyRelative("w").floatValue;
|
||||
|
||||
|
||||
float widthB = width - old_LabelWidth;
|
||||
float fieldWidth = widthB / 4;
|
||||
pos0.width = fieldWidth - 5;
|
||||
|
||||
// Labels
|
||||
pos0.x = old_LabelWidth + 15;
|
||||
GUI.Label(pos0, "Left");
|
||||
|
||||
pos0.x += fieldWidth;
|
||||
GUI.Label(pos0, "Top");
|
||||
|
||||
pos0.x += fieldWidth;
|
||||
GUI.Label(pos0, "Right");
|
||||
|
||||
pos0.x += fieldWidth;
|
||||
GUI.Label(pos0, "Bottom");
|
||||
|
||||
pos0.y += 18;
|
||||
|
||||
pos0.x = old_LabelWidth + 15;
|
||||
vec.x = EditorGUI.FloatField(pos0, GUIContent.none, vec.x);
|
||||
|
||||
pos0.x += fieldWidth;
|
||||
vec.y = EditorGUI.FloatField(pos0, GUIContent.none, vec.y);
|
||||
|
||||
pos0.x += fieldWidth;
|
||||
vec.z = EditorGUI.FloatField(pos0, GUIContent.none, vec.z);
|
||||
|
||||
pos0.x += fieldWidth;
|
||||
vec.w = EditorGUI.FloatField(pos0, GUIContent.none, vec.w);
|
||||
|
||||
//property.vector4Value = vec;
|
||||
property.FindPropertyRelative("x").floatValue = vec.x;
|
||||
property.FindPropertyRelative("y").floatValue = vec.y;
|
||||
property.FindPropertyRelative("z").floatValue = vec.z;
|
||||
property.FindPropertyRelative("w").floatValue = vec.w;
|
||||
|
||||
EditorGUIUtility.labelWidth = old_LabelWidth;
|
||||
EditorGUIUtility.fieldWidth = old_FieldWidth;
|
||||
}
|
||||
|
||||
|
||||
Vector2 GetAnchorPosition(int index)
|
||||
{
|
||||
Vector2 anchorPosition = Vector2.zero;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0: // TOP LEFT
|
||||
anchorPosition = new Vector2(0, 1);
|
||||
break;
|
||||
case 1: // TOP
|
||||
anchorPosition = new Vector2(0.5f, 1);
|
||||
break;
|
||||
case 2: // TOP RIGHT
|
||||
anchorPosition = new Vector2(1, 1);
|
||||
break;
|
||||
case 3: // LEFT
|
||||
anchorPosition = new Vector2(0, 0.5f);
|
||||
break;
|
||||
case 4: // MIDDLE
|
||||
anchorPosition = new Vector2(0.5f, 0.5f);
|
||||
break;
|
||||
case 5: // RIGHT
|
||||
anchorPosition = new Vector2(1, 0.5f);
|
||||
break;
|
||||
case 6: // BOTTOM LEFT
|
||||
anchorPosition = new Vector2(0, 0);
|
||||
break;
|
||||
case 7: // BOTTOM
|
||||
anchorPosition = new Vector2(0.5f, 0);
|
||||
break;
|
||||
case 8: // BOTTOM RIGHT
|
||||
anchorPosition = new Vector2(1, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
return anchorPosition;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02893ffb522b490a9fa28eedd2584309
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,75 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
namespace TMPro.EditorUtilities
|
||||
{
|
||||
|
||||
public class TMPro_TexturePostProcessor : AssetPostprocessor
|
||||
{
|
||||
|
||||
void OnPostprocessTexture(Texture2D texture)
|
||||
{
|
||||
//var importer = assetImporter as TextureImporter;
|
||||
|
||||
Texture2D tex = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Texture2D)) as Texture2D;
|
||||
|
||||
// Send Event Sub Objects
|
||||
if (tex != null)
|
||||
TMPro_EventManager.ON_SPRITE_ASSET_PROPERTY_CHANGED(true, tex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//public class TMPro_PackageImportPostProcessor : AssetPostprocessor
|
||||
//{
|
||||
// static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
|
||||
// {
|
||||
// for (int i = 0; i < importedAssets.Length; i++)
|
||||
// {
|
||||
// if (importedAssets[i].Contains("TextMesh Pro/Resources/TMP Settings.asset"))
|
||||
// {
|
||||
// Debug.Log("New TMP Settings file was just imported.");
|
||||
|
||||
// // TMP Settings file was just re-imported.
|
||||
// // Check if project already contains
|
||||
// }
|
||||
|
||||
|
||||
// if (importedAssets[i].Contains("com.unity.TextMeshPro/Examples"))
|
||||
// {
|
||||
// //Debug.Log("New TMP Examples folder was just imported.");
|
||||
// }
|
||||
|
||||
// //Debug.Log("[" + importedAssets[i] + "] was just imported.");
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// //for (int i = 0; i < deletedAssets.Length; i++)
|
||||
// //{
|
||||
// // if (deletedAssets[i] == "Assets/TextMesh Pro")
|
||||
// // {
|
||||
// // //Debug.Log("Asset [" + deletedAssets[i] + "] has been deleted.");
|
||||
// // string currentBuildSettings = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
|
||||
|
||||
// // //Check for and inject TMP_PRESENT
|
||||
// // if (currentBuildSettings.Contains("TMP_PRESENT;"))
|
||||
// // {
|
||||
// // currentBuildSettings = currentBuildSettings.Replace("TMP_PRESENT;", "");
|
||||
|
||||
// // PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, currentBuildSettings);
|
||||
// // }
|
||||
// // else if (currentBuildSettings.Contains("TMP_PRESENT"))
|
||||
// // {
|
||||
// // currentBuildSettings = currentBuildSettings.Replace("TMP_PRESENT", "");
|
||||
|
||||
// // PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, currentBuildSettings);
|
||||
// // }
|
||||
// // }
|
||||
// //}
|
||||
// }
|
||||
//}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4935fb862d54980b1bcbca942962642
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "Unity.TextMeshPro.Editor",
|
||||
"references": [
|
||||
"Unity.TextMeshPro",
|
||||
"Unity.ugui",
|
||||
"Unity.ugui.Editor"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": []
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6546d7765b4165b40850b3667f981c26
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user