123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- #region copyright
- //-------------------------------------------------------
- // Copyright (C) Dmitriy Yukhanov [https://codestage.net]
- //-------------------------------------------------------
- #endregion
- namespace CodeStage.AdvancedFPSCounter.Labels
- {
- using System.Text;
- using UnityEngine;
- using UnityEngine.UI;
- internal class DrawableLabel
- {
- // ----------------------------------------------------------------------------
- // internal fields
- // ----------------------------------------------------------------------------
- internal GameObject container;
- internal LabelAnchor anchor;
- internal StringBuilder newText;
- internal bool dirty;
- // ----------------------------------------------------------------------------
- // private fields
- // ----------------------------------------------------------------------------
- private GameObject labelGameObject;
- private RectTransform labelTransform;
- private ContentSizeFitter labelFitter;
- private HorizontalLayoutGroup labelGroup;
- private GameObject uiTextGameObject;
- private Text uiText;
- private Font font;
- private int fontSize;
- private float lineSpacing;
- private Vector2 pixelOffset;
- private readonly LabelEffect background;
- private Image backgroundImage;
- private readonly LabelEffect shadow;
- private Shadow shadowComponent;
- private readonly LabelEffect outline;
- private Outline outlineComponent;
- // ----------------------------------------------------------------------------
- // constructor
- // ----------------------------------------------------------------------------
- internal DrawableLabel(GameObject container, LabelAnchor anchor, LabelEffect background, LabelEffect shadow, LabelEffect outline, Font font, int fontSize, float lineSpacing, Vector2 pixelOffset)
- {
- this.container = container;
- this.anchor = anchor;
- this.background = background;
- this.shadow = shadow;
- this.outline = outline;
- this.font = font;
- this.fontSize = fontSize;
- this.lineSpacing = lineSpacing;
- this.pixelOffset = pixelOffset;
- NormalizeOffset();
- newText = new StringBuilder(1000);
- }
- // ----------------------------------------------------------------------------
- // internal methods
- // ----------------------------------------------------------------------------
- internal void CheckAndUpdate()
- {
- if (newText.Length > 0)
- {
- if (uiText == null)
- {
- /* create label game object and configure it */
- labelGameObject = new GameObject(anchor.ToString(), typeof(RectTransform));
- labelTransform = labelGameObject.GetComponent<RectTransform>();
- labelGameObject.layer = container.layer;
- labelGameObject.tag = container.tag;
- labelGameObject.transform.SetParent(container.transform, false);
- uiTextGameObject = new GameObject("Text", typeof(Text));
- uiTextGameObject.transform.SetParent(labelGameObject.transform, false);
- var textRectTransform = (RectTransform)uiTextGameObject.transform;
- textRectTransform.anchorMin = Vector2.zero;
- textRectTransform.anchorMax = Vector2.one;
- textRectTransform.sizeDelta = Vector2.zero;
- /* create UI Text component and apply settings */
- uiText = uiTextGameObject.GetComponent<Text>();
- uiText.horizontalOverflow = HorizontalWrapMode.Overflow;
- uiText.verticalOverflow = VerticalWrapMode.Overflow;
- ApplyShadow();
- ApplyOutline();
- ApplyFont();
- uiText.fontSize = fontSize;
- uiText.lineSpacing = lineSpacing;
- UpdateTextPosition();
- ApplyBackground();
- }
- if (dirty)
- {
- uiText.text = newText.ToString();
- ApplyBackground();
- dirty = false;
- }
- newText.Length = 0;
- }
- else if (uiText != null)
- {
- Clear();
- }
- }
- internal void Clear()
- {
- newText.Length = 0;
- if (labelGameObject != null)
- {
- Object.Destroy(labelGameObject);
- labelGameObject = null;
- labelTransform = null;
- uiText = null;
- }
- if (backgroundImage != null)
- {
- Object.Destroy(backgroundImage);
- backgroundImage = null;
- }
- }
- internal void Destroy()
- {
- Clear();
- newText = null;
- }
- internal void ChangeFont(Font labelsFont)
- {
- font = labelsFont;
- ApplyFont();
- ApplyBackground();
- }
- internal void ChangeFontSize(int newSize)
- {
- fontSize = newSize;
- if (uiText != null) uiText.fontSize = fontSize;
- ApplyBackground();
- }
- internal void ChangeOffset(Vector2 newPixelOffset)
- {
- pixelOffset = newPixelOffset;
- NormalizeOffset();
- if (labelTransform != null)
- {
- labelTransform.anchoredPosition = pixelOffset;
- }
- ApplyBackground();
- }
- internal void ChangeLineSpacing(float newValueLineSpacing)
- {
- lineSpacing = newValueLineSpacing;
- if (uiText != null)
- {
- uiText.lineSpacing = newValueLineSpacing;
- }
- ApplyBackground();
- }
- internal void ChangeBackground(bool enabled)
- {
- background.enabled = enabled;
- ApplyBackground();
- }
- internal void ChangeBackgroundColor(Color color)
- {
- background.color = color;
- ApplyBackground();
- }
- public void ChangeBackgroundPadding(int backgroundPadding)
- {
- background.padding = backgroundPadding;
- ApplyBackground();
- }
- internal void ChangeShadow(bool enabled)
- {
- shadow.enabled = enabled;
- ApplyShadow();
- }
- internal void ChangeShadowColor(Color color)
- {
- shadow.color = color;
- ApplyShadow();
- }
- internal void ChangeShadowDistance(Vector2 distance)
- {
- shadow.distance = distance;
- ApplyShadow();
- }
- internal void ChangeOutline(bool enabled)
- {
- outline.enabled = enabled;
- ApplyOutline();
- }
- internal void ChangeOutlineColor(Color color)
- {
- outline.color = color;
- ApplyOutline();
- }
- internal void ChangeOutlineDistance(Vector2 distance)
- {
- outline.distance = distance;
- ApplyOutline();
- }
- // ----------------------------------------------------------------------------
- // private methods
- // ----------------------------------------------------------------------------
- private void UpdateTextPosition()
- {
- labelTransform.localRotation = Quaternion.identity;
- labelTransform.sizeDelta = Vector2.zero;
- labelTransform.anchoredPosition = pixelOffset;
- switch (anchor)
- {
- case LabelAnchor.UpperLeft:
- uiText.alignment = TextAnchor.UpperLeft;
- labelTransform.anchorMin = Vector2.up;
- labelTransform.anchorMax = Vector2.up;
- labelTransform.pivot = new Vector2(0,1);
- break;
- case LabelAnchor.UpperRight:
- uiText.alignment = TextAnchor.UpperRight;
- labelTransform.anchorMin = Vector2.one;
- labelTransform.anchorMax = Vector2.one;
- labelTransform.pivot = new Vector2(1, 1);
- break;
- case LabelAnchor.LowerLeft:
- uiText.alignment = TextAnchor.LowerLeft;
- labelTransform.anchorMin = Vector2.zero;
- labelTransform.anchorMax = Vector2.zero;
- labelTransform.pivot = new Vector2(0, 0);
- break;
- case LabelAnchor.LowerRight:
- uiText.alignment = TextAnchor.LowerRight;
- labelTransform.anchorMin = Vector2.right;
- labelTransform.anchorMax = Vector2.right;
- labelTransform.pivot = new Vector2(1, 0);
- break;
- case LabelAnchor.UpperCenter:
- uiText.alignment = TextAnchor.UpperCenter;
- labelTransform.anchorMin = new Vector2(0.5f, 1f);
- labelTransform.anchorMax = new Vector2(0.5f, 1f);
- labelTransform.pivot = new Vector2(0.5f, 1);
- break;
- case LabelAnchor.LowerCenter:
- uiText.alignment = TextAnchor.LowerCenter;
- labelTransform.anchorMin = new Vector2(0.5f, 0f);
- labelTransform.anchorMax = new Vector2(0.5f, 0f);
- labelTransform.pivot = new Vector2(0.5f, 0);
- break;
- default:
- Debug.LogWarning(AFPSCounter.LogPrefix + "Unknown label anchor!", uiText);
- uiText.alignment = TextAnchor.UpperLeft;
- labelTransform.anchorMin = Vector2.up;
- labelTransform.anchorMax = Vector2.up;
- break;
- }
- }
- private void NormalizeOffset()
- {
- switch (anchor)
- {
- case LabelAnchor.UpperLeft:
- pixelOffset.y = -pixelOffset.y;
- break;
- case LabelAnchor.UpperRight:
- pixelOffset.x = -pixelOffset.x;
- pixelOffset.y = -pixelOffset.y;
- break;
- case LabelAnchor.LowerLeft:
- // it's fine
- break;
- case LabelAnchor.LowerRight:
- pixelOffset.x = -pixelOffset.x;
- break;
- case LabelAnchor.UpperCenter:
- pixelOffset.y = -pixelOffset.y;
- pixelOffset.x = 0;
- break;
- case LabelAnchor.LowerCenter:
- pixelOffset.x = 0;
- break;
- default:
- pixelOffset.y = -pixelOffset.y;
- break;
- }
- }
- private void ApplyBackground()
- {
- if (uiText == null) return;
- if (background.enabled && !backgroundImage)
- {
- backgroundImage = labelGameObject.AddComponent<Image>();
- labelFitter = labelGameObject.AddComponent<ContentSizeFitter>();
- labelFitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
- labelFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
- labelGroup = labelGameObject.AddComponent<HorizontalLayoutGroup>();
- }
- if (!background.enabled && backgroundImage)
- {
- Object.Destroy(backgroundImage);
- Object.Destroy(labelFitter);
- Object.Destroy(labelGroup);
- backgroundImage = null;
- }
- if (backgroundImage != null)
- {
- if (backgroundImage.color != background.color)
- {
- backgroundImage.color = background.color;
- }
- if (labelGroup.padding.bottom != background.padding)
- {
- labelGroup.padding.top = background.padding;
- labelGroup.padding.left = background.padding;
- labelGroup.padding.right = background.padding;
- labelGroup.padding.bottom = background.padding;
- labelGroup.SetLayoutHorizontal();
- }
- }
- }
- private void ApplyShadow()
- {
- if (uiText == null) return;
- if (shadow.enabled && !shadowComponent)
- {
- shadowComponent = uiTextGameObject.AddComponent<Shadow>();
- }
- if (!shadow.enabled && shadowComponent)
- {
- Object.Destroy(shadowComponent);
- }
- if (shadowComponent != null)
- {
- shadowComponent.effectColor = shadow.color;
- shadowComponent.effectDistance = shadow.distance;
- }
- }
- private void ApplyOutline()
- {
- if (uiText == null) return;
- if (outline.enabled && !outlineComponent)
- {
- outlineComponent = uiTextGameObject.AddComponent<Outline>();
- }
- if (!outline.enabled && outlineComponent)
- {
- Object.Destroy(outlineComponent);
- }
- if (outlineComponent != null)
- {
- outlineComponent.effectColor = outline.color;
- outlineComponent.effectDistance = outline.distance;
- }
- }
- private void ApplyFont()
- {
- if (uiText == null) return;
- if (font == null) font = Resources.GetBuiltinResource<Font>("Arial.ttf");
- uiText.font = font;
- }
- }
- }
|