Hue Preserving Color Blending
TMP_SubMesh.cs
1 using UnityEngine;
2 using System;
3 using System.Collections;
4 
5 #pragma warning disable 0109 // Disable warning due to conflict between Unity Editor DLL and Runtime DLL related to .renderer property being available in one but not the other.
6 
7 namespace TMPro
8 {
9 
10  [ExecuteInEditMode]
11  [RequireComponent(typeof(MeshRenderer))]
12  [RequireComponent(typeof(MeshFilter))]
13  public class TMP_SubMesh : MonoBehaviour
14  {
19  {
20  get { return m_fontAsset; }
21  set { m_fontAsset = value; }
22  }
23  [SerializeField]
24  private TMP_FontAsset m_fontAsset;
25 
26 
31  {
32  get { return m_spriteAsset; }
33  set { m_spriteAsset = value; }
34  }
35  [SerializeField]
36  private TMP_SpriteAsset m_spriteAsset;
37 
38 
42  public Material material
43  {
44  // Return a new Instance of the Material if none exists. Otherwise return the current Material Instance.
45  get { return GetMaterial(m_sharedMaterial); }
46 
47  // Assign new font material
48  set
49  {
50  if (m_sharedMaterial.GetInstanceID() == value.GetInstanceID())
51  return;
52 
53  m_sharedMaterial = m_material = value;
54 
55  m_padding = GetPaddingForMaterial();
56 
59  }
60  }
61  [SerializeField]
62  private Material m_material;
63 
64 
68  public Material sharedMaterial
69  {
70  get { return m_sharedMaterial; }
71  set { SetSharedMaterial(value); }
72  }
73  [SerializeField]
74  private Material m_sharedMaterial;
75 
76 
80  public Material fallbackMaterial
81  {
82  get { return m_fallbackMaterial; }
83  set
84  {
85  if (m_fallbackMaterial == value) return;
86 
87  if (m_fallbackMaterial != null && m_fallbackMaterial != value)
88  TMP_MaterialManager.ReleaseFallbackMaterial(m_fallbackMaterial);
89 
90  m_fallbackMaterial = value;
91  TMP_MaterialManager.AddFallbackMaterialReference(m_fallbackMaterial);
92 
93  SetSharedMaterial(m_fallbackMaterial);
94  }
95  }
96  private Material m_fallbackMaterial;
97 
98 
102  public Material fallbackSourceMaterial
103  {
104  get { return m_fallbackSourceMaterial; }
105  set { m_fallbackSourceMaterial = value; }
106  }
107  private Material m_fallbackSourceMaterial;
108 
109 
113  public bool isDefaultMaterial
114  {
115  get { return m_isDefaultMaterial; }
116  set { m_isDefaultMaterial = value; }
117  }
118  [SerializeField]
119  private bool m_isDefaultMaterial;
120 
121 
125  public float padding
126  {
127  get { return m_padding; }
128  set { m_padding = value; }
129  }
130  [SerializeField]
131  private float m_padding;
132 
133 
137  public new Renderer renderer
138  {
139  get { if (m_renderer == null) m_renderer = GetComponent<Renderer>();
140 
141  return m_renderer;
142  }
143  }
144  [SerializeField]
145  private Renderer m_renderer;
146 
147 
151  public MeshFilter meshFilter
152  {
153  get { if (m_meshFilter == null) m_meshFilter = GetComponent<MeshFilter>();
154  return m_meshFilter;
155  }
156  }
157  [SerializeField]
158  private MeshFilter m_meshFilter;
159 
160 
164  public Mesh mesh
165  {
166  get
167  {
168  if (m_mesh == null)
169  {
170  m_mesh = new Mesh();
171  m_mesh.hideFlags = HideFlags.HideAndDontSave;
172  this.meshFilter.mesh = m_mesh;
173  }
174 
175  return m_mesh;
176  }
177  set { m_mesh = value; }
178  }
179  private Mesh m_mesh;
180 
184  //public BoxCollider boxCollider
185  //{
186  // get
187  // {
188  // if (m_boxCollider == null)
189  // {
190  // //
191  // m_boxCollider = GetComponent<BoxCollider>();
192  // if (m_boxCollider == null)
193  // {
194  // m_boxCollider = gameObject.AddComponent<BoxCollider>();
195  // gameObject.AddComponent<Rigidbody>();
196  // }
197  // }
198 
199  // return m_boxCollider;
200  // }
201  //}
202  //[SerializeField]
203  //private BoxCollider m_boxCollider;
204 
205  [SerializeField]
207 
208  [NonSerialized]
209  private bool m_isRegisteredForEvents;
210 
211 
212  void OnEnable()
213  {
214  // Register Callbacks for various events.
215  if (!m_isRegisteredForEvents)
216  {
217 #if UNITY_EDITOR
218  TMPro_EventManager.MATERIAL_PROPERTY_EVENT.Add(ON_MATERIAL_PROPERTY_CHANGED);
219  TMPro_EventManager.FONT_PROPERTY_EVENT.Add(ON_FONT_PROPERTY_CHANGED);
220  //TMPro_EventManager.TEXTMESHPRO_PROPERTY_EVENT.Add(ON_TEXTMESHPRO_PROPERTY_CHANGED);
221  TMPro_EventManager.DRAG_AND_DROP_MATERIAL_EVENT.Add(ON_DRAG_AND_DROP_MATERIAL);
222  //TMPro_EventManager.TEXT_STYLE_PROPERTY_EVENT.Add(ON_TEXT_STYLE_CHANGED);
223  TMPro_EventManager.SPRITE_ASSET_PROPERTY_EVENT.Add(ON_SPRITE_ASSET_PROPERTY_CHANGED);
224  //TMPro_EventManager.TMP_SETTINGS_PROPERTY_EVENT.Add(ON_TMP_SETTINGS_CHANGED);
225 #endif
226 
227  m_isRegisteredForEvents = true;
228  }
229 
230  // Make the geometry visible when the object is enabled.
231  meshFilter.sharedMesh = mesh;
232 
233  // Update _ClipRect values
234  if (m_sharedMaterial != null)
235  m_sharedMaterial.SetVector(ShaderUtilities.ID_ClipRect, new Vector4(-32767, -32767, 32767, 32767));
236  }
237 
238 
239  void OnDisable()
240  {
241  // Hide the geometry when the object is disabled.
242  m_meshFilter.sharedMesh = null;
243 
244  if (m_fallbackMaterial != null)
245  {
246  TMP_MaterialManager.ReleaseFallbackMaterial(m_fallbackMaterial);
247  m_fallbackMaterial = null;
248  }
249 
250 
251  }
252 
253 
254  void OnDestroy()
255  {
256  // Destroy Mesh
257  if (m_mesh != null) DestroyImmediate(m_mesh);
258 
259  if (m_fallbackMaterial != null)
260  {
261  TMP_MaterialManager.ReleaseFallbackMaterial(m_fallbackMaterial);
262  m_fallbackMaterial = null;
263  }
264 
265 #if UNITY_EDITOR
266  // Unregister the event this object was listening to
267  TMPro_EventManager.MATERIAL_PROPERTY_EVENT.Remove(ON_MATERIAL_PROPERTY_CHANGED);
268  TMPro_EventManager.FONT_PROPERTY_EVENT.Remove(ON_FONT_PROPERTY_CHANGED);
269  //TMPro_EventManager.TEXTMESHPRO_PROPERTY_EVENT.Remove(ON_TEXTMESHPRO_PROPERTY_CHANGED);
270  TMPro_EventManager.DRAG_AND_DROP_MATERIAL_EVENT.Remove(ON_DRAG_AND_DROP_MATERIAL);
271  //TMPro_EventManager.TEXT_STYLE_PROPERTY_EVENT.Remove(ON_TEXT_STYLE_CHANGED);
272  TMPro_EventManager.SPRITE_ASSET_PROPERTY_EVENT.Remove(ON_SPRITE_ASSET_PROPERTY_CHANGED);
273  //TMPro_EventManager.TMP_SETTINGS_PROPERTY_EVENT.Remove(ON_TMP_SETTINGS_CHANGED);
274 #endif
275  m_isRegisteredForEvents = false;
276  }
277 
278 
279 
280 #if UNITY_EDITOR
281  // Event received when custom material editor properties are changed.
282  void ON_MATERIAL_PROPERTY_CHANGED(bool isChanged, Material mat)
283  {
284  //Debug.Log("*** ON_MATERIAL_PROPERTY_CHANGED ***");
285  int targetMaterialID = mat.GetInstanceID();
286  int sharedMaterialID = m_sharedMaterial.GetInstanceID();
287  int fallbackSourceMaterialID = m_fallbackSourceMaterial == null ? 0 : m_fallbackSourceMaterial.GetInstanceID();
288 
289  // Filter events and return if the affected material is not this object's material.
290  if (targetMaterialID != sharedMaterialID)
291  {
292  // Check if event applies to the source fallback material
293  if (m_fallbackMaterial != null && fallbackSourceMaterialID == targetMaterialID)
294  TMP_MaterialManager.CopyMaterialPresetProperties(mat, m_fallbackMaterial);
295  else
296  return;
297  }
298 
299  if (m_TextComponent == null) m_TextComponent = GetComponentInParent<TextMeshPro>();
300 
301  m_padding = GetPaddingForMaterial();
302 
305  }
306 
307 
308  // Event to Track Material Changed resulting from Drag-n-drop.
309  void ON_DRAG_AND_DROP_MATERIAL(GameObject obj, Material currentMaterial, Material newMaterial)
310  {
311  // Check if event applies to this current object
312  #if UNITY_2018_2_OR_NEWER
313  if (obj == gameObject || UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(gameObject) == obj)
314  #else
315  if (obj == gameObject || UnityEditor.PrefabUtility.GetPrefabParent(gameObject) == obj)
316  #endif
317  {
318  if (!m_isDefaultMaterial) return;
319 
320  // Make sure we have a valid reference to the renderer.
321  if (m_renderer == null) m_renderer = GetComponent<Renderer>();
322 
323  UnityEditor.Undo.RecordObject(this, "Material Assignment");
324  UnityEditor.Undo.RecordObject(m_renderer, "Material Assignment");
325 
326  SetSharedMaterial(newMaterial);
328  }
329  }
330 
331 
332  // Event received when font asset properties are changed in Font Inspector
333  void ON_SPRITE_ASSET_PROPERTY_CHANGED(bool isChanged, UnityEngine.Object obj)
334  {
335  //if (spriteSheet != null && (obj as TMP_SpriteAsset == m_spriteAsset || obj as Texture2D == m_spriteAsset.spriteSheet))
336  //{
337  if (m_TextComponent != null)
338  {
340  //m_TextComponent.SetVerticesDirty();
341  }
342 
343  //}
344  }
345 
346  // Event received when font asset properties are changed in Font Inspector
347  void ON_FONT_PROPERTY_CHANGED(bool isChanged, TMP_FontAsset font)
348  {
349  if (m_fontAsset != null && font.GetInstanceID() == m_fontAsset.GetInstanceID())
350  {
351  // Copy Normal and Bold Weight
352  if (m_fallbackMaterial != null)
353  {
354  m_fallbackMaterial.SetFloat(ShaderUtilities.ID_WeightNormal, m_fontAsset.normalStyle);
355  m_fallbackMaterial.SetFloat(ShaderUtilities.ID_WeightBold, m_fontAsset.boldStyle);
356  }
357  }
358  }
359 
363  void ON_TMP_SETTINGS_CHANGED()
364  {
365  // //Debug.Log("TMP Setting have changed.");
366  // //SetVerticesDirty();
367  // SetMaterialDirty();
368  }
369 #endif
370 
371 
372 
373  public static TMP_SubMesh AddSubTextObject(TextMeshPro textComponent, MaterialReference materialReference)
374  {
375  GameObject go = new GameObject("TMP SubMesh [" + materialReference.material.name + "]", typeof(TMP_SubMesh));
376 
377  TMP_SubMesh subMesh = go.GetComponent<TMP_SubMesh>();
378 
379  go.transform.SetParent(textComponent.transform, false);
380  go.transform.localPosition = Vector3.zero;
381  go.transform.localRotation = Quaternion.identity;
382  go.transform.localScale = Vector3.one;
383  go.layer = textComponent.gameObject.layer;
384 
385  subMesh.m_meshFilter = go.GetComponent<MeshFilter>();
386 
387  subMesh.m_TextComponent = textComponent;
388  subMesh.m_fontAsset = materialReference.fontAsset;
389  subMesh.m_spriteAsset = materialReference.spriteAsset;
390  subMesh.m_isDefaultMaterial = materialReference.isDefaultMaterial;
391  subMesh.SetSharedMaterial(materialReference.material);
392 
393  subMesh.renderer.sortingLayerID = textComponent.renderer.sortingLayerID;
394  subMesh.renderer.sortingOrder = textComponent.renderer.sortingOrder;
395 
396  return subMesh;
397  }
398 
399 
400  public void DestroySelf()
401  {
402  Destroy(this.gameObject, 1f);
403  }
404 
405  // Function called internally when a new material is assigned via the fontMaterial property.
406  Material GetMaterial(Material mat)
407  {
408  // Check in case Object is disabled. If so, we don't have a valid reference to the Renderer.
409  // This can occur when the Duplicate Material Context menu is used on an inactive object.
410  if (m_renderer == null)
411  m_renderer = GetComponent<Renderer>();
412 
413  // Create Instance Material only if the new material is not the same instance previously used.
414  if (m_material == null || m_material.GetInstanceID() != mat.GetInstanceID())
415  m_material = CreateMaterialInstance(mat);
416 
417  m_sharedMaterial = m_material;
418 
419  // Compute and Set new padding values for this new material.
420  m_padding = GetPaddingForMaterial();
421 
424 
425  return m_sharedMaterial;
426  }
427 
428 
434  Material CreateMaterialInstance(Material source)
435  {
436  Material mat = new Material(source);
437  mat.shaderKeywords = source.shaderKeywords;
438  mat.name += " (Instance)";
439 
440  return mat;
441  }
442 
443 
448  Material GetSharedMaterial()
449  {
450  if (m_renderer == null)
451  m_renderer = GetComponent<Renderer>();
452 
453  return m_renderer.sharedMaterial;
454  }
455 
456 
461  void SetSharedMaterial(Material mat)
462  {
463  //Debug.Log("*** SetSharedMaterial() *** FRAME (" + Time.frameCount + ")");
464 
465  // Assign new material.
466  m_sharedMaterial = mat;
467 
468  // Compute and Set new padding values for this new material.
469  m_padding = GetPaddingForMaterial();
470 
472 
473 #if UNITY_EDITOR
474  if (m_sharedMaterial != null)
475  gameObject.name = "TMP SubMesh [" + m_sharedMaterial.name + "]";
476 #endif
477  }
478 
479 
484  public float GetPaddingForMaterial()
485  {
486  float padding = ShaderUtilities.GetPadding(m_sharedMaterial, m_TextComponent.extraPadding, m_TextComponent.isUsingBold);
487 
488  return padding;
489  }
490 
491 
497  public void UpdateMeshPadding(bool isExtraPadding, bool isUsingBold)
498  {
499  m_padding = ShaderUtilities.GetPadding(m_sharedMaterial, isExtraPadding, isUsingBold);
500  }
501 
502 
506  public void SetVerticesDirty()
507  {
508  if (!this.enabled)
509  return;
510 
511  // This is called on the parent TextMeshPro component.
512  if (m_TextComponent != null)
513  {
516  }
517  }
518 
519 
523  public void SetMaterialDirty()
524  {
525  //if (!this.enabled)
526  // return;
527 
528  UpdateMaterial();
529 
530  //m_materialDirty = true;
531  //TMP_UpdateRegistry.RegisterCanvasElementForGraphicRebuild((ICanvasElement)this);
532  }
533 
534 
538  protected void UpdateMaterial()
539  {
540  //Debug.Log("*** STO - UpdateMaterial() *** FRAME (" + Time.frameCount + ")");
541 
542  //if (!this.enabled)
543  // return;
544 
545  if (m_renderer == null) m_renderer = this.renderer;
546 
547  m_renderer.sharedMaterial = m_sharedMaterial;
548 
549 #if UNITY_EDITOR
550  if (m_sharedMaterial != null && gameObject.name != "TMP SubMesh [" + m_sharedMaterial.name + "]")
551  gameObject.name = "TMP SubMesh [" + m_sharedMaterial.name + "]";
552 #endif
553  }
554 
558  //public void UpdateColliders(int vertexCount)
559  //{
560  // if (this.boxCollider == null) return;
561 
562  // Vector2 bl = TMP_Math.MAX_16BIT;
563  // Vector2 tr = TMP_Math.MIN_16BIT;
564  // // Compute the bounds of the sub text object mesh (excluding the transform position).
565  // for (int i = 0; i < vertexCount; i++)
566  // {
567  // bl.x = Mathf.Min(bl.x, m_mesh.vertices[i].x);
568  // bl.y = Mathf.Min(bl.y, m_mesh.vertices[i].y);
569 
570  // tr.x = Mathf.Max(tr.x, m_mesh.vertices[i].x);
571  // tr.y = Mathf.Max(tr.y, m_mesh.vertices[i].y);
572  // }
573 
574  // Vector3 center = (bl + tr) / 2;
575  // Vector3 size = tr - bl;
576  // size.z = .1f;
577  // this.boxCollider.center = center;
578  // this.boxCollider.size = size;
579  //}
580  }
581 }
Mesh mesh
The Mesh of this text sub object.
Definition: TMP_SubMesh.cs:165
void UpdateMeshPadding(bool isExtraPadding, bool isUsingBold)
Function to update the padding values of the object.
Definition: TMP_SubMesh.cs:497
bool isDefaultMaterial
Is the text object using the default font asset material.
Definition: TMP_SubMesh.cs:114
override void SetVerticesDirty()
Schedule rebuilding of the text geometry.
Definition: TextMeshPro.cs:166
void SetMaterialDirty()
Definition: TMP_SubMesh.cs:523
TextMeshPro m_TextComponent
Definition: TMP_SubMesh.cs:206
float padding
Padding value resulting for the property settings on the material.
Definition: TMP_SubMesh.cs:126
bool havePropertiesChanged
Property tracking if any of the text properties have changed. Flag is set before the text is regenera...
Definition: TMP_Text.cs:1024
Material sharedMaterial
The material to be assigned to this text object.
Definition: TMP_SubMesh.cs:69
TMP_SpriteAsset spriteAsset
The TMP Sprite Asset assigned to this sub text object.
Definition: TMP_SubMesh.cs:31
void SetSharedMaterial(Material mat)
Method to set the shared material.
Definition: TMP_SubMesh.cs:461
Material CreateMaterialInstance(Material source)
Method used to create an instance of the material
Definition: TMP_SubMesh.cs:434
Material GetSharedMaterial()
Method returning the shared material assigned to the text object.
Definition: TMP_SubMesh.cs:448
bool isUsingBold
Property used in conjunction with padding calculation for the geometry.
Definition: TMP_Text.cs:499
Material material
The material to be assigned to this object. Returns an instance of the material.
Definition: TMP_SubMesh.cs:43
void SetVerticesDirty()
Definition: TMP_SubMesh.cs:506
bool extraPadding
Adds extra padding around each character. This may be necessary when the displayed text is very small...
Definition: TMP_Text.cs:761
Material fallbackMaterial
The fallback material created from the properties of the fallback source material.
Definition: TMP_SubMesh.cs:81
Material fallbackSourceMaterial
The source material used by the fallback font
Definition: TMP_SubMesh.cs:103
TMP_FontAsset fontAsset
The TMP Font Asset assigned to this sub text object.
Definition: TMP_SubMesh.cs:19
new Renderer renderer
The Mesh Renderer of this text sub object.
Definition: TMP_SubMesh.cs:138
float GetPaddingForMaterial()
Function called when the padding value for the material needs to be re-calculated.
Definition: TMP_SubMesh.cs:484
MeshFilter meshFilter
The MeshFilter of this text sub object.
Definition: TMP_SubMesh.cs:152