Last active
May 5, 2016 15:32
-
-
Save JamesMcMahon/578a842fd18641ea9c36761b03b09801 to your computer and use it in GitHub Desktop.
Unity inline image in text script. Could never get it to work properly on Android (didn't even test iOS). Quad placeholder would leave behind vector noise. Heavily modified from original at http://forum.unity3d.com/threads/sprite-icons-with-text-e-g-emoticons.265927/#post-2466522. Hopefully DMGregor (http://gamedev.stackexchange.com/q/88502/6968)…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Text.RegularExpressions; | |
using UnityEngine; | |
using UnityEngine.UI; | |
// Usage: icon name in text is replaced by image | |
public class TextPic : Text | |
{ | |
[System.Serializable] | |
public struct IconName | |
{ | |
public string name; | |
public Sprite sprite; | |
} | |
/// <summary> | |
/// Regular expression to replace | |
/// </summary> | |
static readonly Regex s_Regex = | |
new Regex(@"<quad name=(.+?) size=(\d*\.?\d+%?) width=(\d*\.?\d+%?) />", RegexOptions.Singleline); | |
public IconName[] inspectorIconList; | |
// Scale image by x, y | |
[SerializeField] | |
public Vector2 imageScalingFactor = Vector2.one; | |
// Offset image by x, y | |
[SerializeField] | |
public Vector2 imageOffset = Vector2.zero; | |
// Pad image by x | |
public float imagePad; | |
/// <summary> | |
/// Image Pool | |
/// </summary> | |
readonly List<Image> m_ImagesPool = new List<Image>(); | |
/// <summary> | |
/// Vertex Index | |
/// </summary> | |
readonly List<int> m_ImagesVertexIndex = new List<int>(); | |
/// <summary> | |
/// After parsing the final text | |
/// </summary> | |
string m_OutputText; | |
Dictionary<string, Sprite> iconList = new Dictionary<string, Sprite>(); | |
List<Vector2> positions = new List<Vector2>(); | |
public override void SetVerticesDirty() | |
{ | |
base.SetVerticesDirty(); | |
UpdateQuadImage(); | |
} | |
protected override void OnPopulateMesh(VertexHelper toFill) | |
{ | |
var orignText = m_Text; | |
m_Text = m_OutputText; | |
base.OnPopulateMesh(toFill); | |
m_Text = orignText; | |
positions.Clear(); | |
var vert = new UIVertex(); | |
for (var i = 0; i < m_ImagesVertexIndex.Count; i++) | |
{ | |
var endIndex = m_ImagesVertexIndex[i]; | |
var rt = m_ImagesPool[i].rectTransform; | |
var size = rt.sizeDelta; | |
if (endIndex < toFill.currentVertCount) | |
{ | |
toFill.PopulateUIVertex(ref vert, endIndex); | |
var position = new Vector2((vert.position.x + size.x / 2), (vert.position.y + size.y / 2)); | |
position += imageOffset; | |
if (i > 0) | |
{ | |
var padVector = new Vector2(imagePad * i, 0); | |
position += padVector; | |
} | |
positions.Add(position); | |
// Erase the lower left corner of the black specks | |
var end = endIndex - 3; | |
toFill.PopulateUIVertex(ref vert, end); | |
var pos = vert.position; | |
for (int j = endIndex; j > end; j--) | |
{ | |
toFill.PopulateUIVertex(ref vert, endIndex); | |
vert.position = pos; | |
toFill.SetUIVertex(vert, j); | |
} | |
} | |
} | |
if (m_ImagesVertexIndex.Count != 0) | |
{ | |
m_ImagesVertexIndex.Clear(); | |
} | |
} | |
/** | |
* Unity Inspector cant display Dictionary vars, | |
* so we use this little hack to setup the iconList | |
*/ | |
new void Start() | |
{ | |
if (inspectorIconList != null) | |
{ | |
foreach (IconName icon in inspectorIconList) | |
{ | |
iconList.Add(icon.name, icon.sprite); | |
} | |
} | |
} | |
void UpdateQuadImage() | |
{ | |
#if UNITY_EDITOR | |
if (UnityEditor.PrefabUtility.GetPrefabType(this) == UnityEditor.PrefabType.Prefab) | |
{ | |
return; | |
} | |
#endif | |
m_OutputText = GetOutputText(); | |
m_ImagesVertexIndex.Clear(); | |
foreach (Match match in s_Regex.Matches(m_OutputText)) | |
{ | |
var picIndex = match.Index; | |
var endIndex = picIndex * 4 + 3; | |
m_ImagesVertexIndex.Add(endIndex); | |
m_ImagesPool.RemoveAll(image => image == null); | |
if (m_ImagesPool.Count == 0) | |
{ | |
GetComponentsInChildren<Image>(m_ImagesPool); | |
} | |
if (m_ImagesVertexIndex.Count > m_ImagesPool.Count) | |
{ | |
var resources = new DefaultControls.Resources(); | |
var go = DefaultControls.CreateImage(resources); | |
go.layer = gameObject.layer; | |
var rt = go.transform as RectTransform; | |
if (rt) | |
{ | |
rt.SetParent(rectTransform); | |
rt.localPosition = Vector3.zero; | |
rt.localRotation = Quaternion.identity; | |
rt.localScale = Vector3.one; | |
} | |
m_ImagesPool.Add(go.GetComponent<Image>()); | |
} | |
var spriteName = match.Groups[1].Value; | |
var img = m_ImagesPool[m_ImagesVertexIndex.Count - 1]; | |
if (img.sprite == null || img.sprite.name != spriteName) | |
{ | |
if (inspectorIconList != null && inspectorIconList.Length > 0) | |
{ | |
foreach (IconName icon in inspectorIconList) | |
{ | |
if (icon.name == spriteName) | |
{ | |
img.sprite = icon.sprite; | |
break; | |
} | |
} | |
} | |
} | |
img.rectTransform.sizeDelta = new Vector2(fontSize * imageScalingFactor.x, fontSize * imageScalingFactor.y); | |
img.enabled = true; | |
if (positions.Count == m_ImagesPool.Count) | |
{ | |
img.rectTransform.anchoredPosition = positions[m_ImagesVertexIndex.Count - 1]; | |
} | |
} | |
for (var i = m_ImagesVertexIndex.Count; i < m_ImagesPool.Count; i++) | |
{ | |
if (m_ImagesPool[i]) | |
{ | |
m_ImagesPool[i].enabled = false; | |
} | |
} | |
} | |
string GetOutputText() | |
{ | |
var fixedString = this.text; | |
if (inspectorIconList != null && inspectorIconList.Length > 0) | |
{ | |
foreach (IconName icon in inspectorIconList) | |
{ | |
if (!string.IsNullOrEmpty(icon.name)) | |
{ | |
fixedString = fixedString.Replace(icon.name, "<quad name=" + icon.name + " size=" + fontSize + " width=1 />"); | |
} | |
} | |
} | |
return fixedString; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEditor; | |
using UnityEngine; | |
using TextEditor = UnityEditor.UI.TextEditor; | |
[CanEditMultipleObjects] | |
[CustomEditor(typeof(TextPic))] | |
public class TextPicEditor : TextEditor | |
{ | |
SerializedProperty imageScalingFactorProp; | |
SerializedProperty imageOffsetProp; | |
SerializedProperty imagePadProp; | |
SerializedProperty iconList; | |
protected override void OnEnable() | |
{ | |
base.OnEnable(); | |
imageScalingFactorProp = serializedObject.FindProperty("imageScalingFactor"); | |
imageOffsetProp = serializedObject.FindProperty("imageOffset"); | |
imagePadProp = serializedObject.FindProperty("imagePad"); | |
iconList = serializedObject.FindProperty("inspectorIconList"); | |
} | |
public override void OnInspectorGUI() | |
{ | |
base.OnInspectorGUI(); | |
serializedObject.Update(); | |
EditorGUILayout.PropertyField(imageOffsetProp, new GUIContent("Image Offset")); | |
EditorGUILayout.PropertyField(imagePadProp, new GUIContent("Image Pad")); | |
EditorGUILayout.PropertyField(imageScalingFactorProp, new GUIContent("Image Scaling Factor")); | |
EditorGUILayout.PropertyField(iconList, new GUIContent("Icon List"), true); | |
serializedObject.ApplyModifiedProperties(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment