< Summary

Class:DCL.Components.TextShape
Assembly:DCL.Components.TextShape
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/TextShape/TextShape.cs
Covered lines:82
Uncovered lines:48
Coverable lines:130
Total lines:297
Line coverage:63% (82 of 130)
Covered branches:0
Total branches:0
Covered methods:13
Total methods:15
Method coverage:86.6% (13 of 15)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Model()0%110100%
GetDataFromJSON(...)0%110100%
GetDataFromPb(...)0%7022600%
Awake()0%110100%
LookToCamera()0%4.594066.67%
GetModel()0%110100%
ApplyChanges()0%7.147085.71%
ApplyModelChanges(...)0%12.9110069.23%
GetAlignment(...)0%990100%
PrepareRectTransform()0%2.012087.5%
GetClassId()0%110100%
Cleanup()0%110100%
OnDestroy()0%220100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/TextShape/TextShape.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using DCL.Helpers;
 4using DCL.Models;
 5using TMPro;
 6using UnityEngine;
 7using Decentraland.Sdk.Ecs6;
 8using MainScripts.DCL.Components;
 9
 10namespace DCL.Components
 11{
 12    public class TextShape : BaseComponent
 13    {
 14        [Serializable]
 15        public class Model : BaseModel
 16        {
 17            public bool billboard;
 18
 19            [Header("Font Properties")]
 34620            public string value = "";
 21
 34622            public bool visible = true;
 23
 34624            public Color color = Color.white;
 34625            public float opacity = 1f;
 34626            public float fontSize = 100f;
 27            public bool fontAutoSize = false;
 28            public string font;
 29
 30            [Header("Text box properties")]
 34631            public string hTextAlign = "bottom";
 34632            public string vTextAlign = "left";
 34633            public float width = 1f;
 34634            public float height = 0.2f;
 35            public float paddingTop = 0f;
 36            public float paddingRight = 0f;
 37            public float paddingBottom = 0f;
 38            public float paddingLeft = 0f;
 39            public float lineSpacing = 0f;
 40            public int lineCount = 0;
 41            public bool textWrapping = false;
 42
 43            [Header("Text shadow properties")]
 44            public float shadowBlur = 0f;
 45            public float shadowOffsetX = 0f;
 46            public float shadowOffsetY = 0f;
 34647            public Color shadowColor = new Color(1, 1, 1);
 48
 49            [Header("Text outline properties")]
 50            public float outlineWidth = 0f;
 51
 34652            public Color outlineColor = Color.white;
 53
 1554            public override BaseModel GetDataFromJSON(string json) { return Utils.SafeFromJson<Model>(json); }
 55
 56            public override BaseModel GetDataFromPb(ComponentBodyPayload pbModel)
 57            {
 058                if (pbModel.PayloadCase != ComponentBodyPayload.PayloadOneofCase.TextShape)
 059                    return Utils.SafeUnimplemented<TextShape, Model>(expected: ComponentBodyPayload.PayloadOneofCase.Tex
 60
 061                var model = new Model();
 62
 63                try {
 064                    if (pbModel.TextShape.HasBillboard) model.billboard = pbModel.TextShape.Billboard;
 065                    if (pbModel.TextShape.Color != null) model.color = pbModel.TextShape.Color.AsUnityColor();
 066                    if (pbModel.TextShape.HasFont) model.font = pbModel.TextShape.Font;
 067                    if (pbModel.TextShape.HasHeight) model.height = pbModel.TextShape.Height;
 068                    if (pbModel.TextShape.HasOpacity) model.opacity = pbModel.TextShape.Opacity;
 069                    if (pbModel.TextShape.HasValue) model.value = pbModel.TextShape.Value;
 070                    if (pbModel.TextShape.HasVisible) model.visible = pbModel.TextShape.Visible;
 071                    if (pbModel.TextShape.HasWidth) model.width = pbModel.TextShape.Width;
 072                    if (pbModel.TextShape.HasLineCount) model.lineCount = pbModel.TextShape.LineCount;
 073                    if (pbModel.TextShape.OutlineColor != null) model.outlineColor = pbModel.TextShape.OutlineColor.AsUn
 074                    if (pbModel.TextShape.HasOutlineWidth) model.outlineWidth = pbModel.TextShape.OutlineWidth;
 075                    if (pbModel.TextShape.HasPaddingBottom ) model.paddingBottom = pbModel.TextShape.PaddingBottom;
 076                    if (pbModel.TextShape.HasPaddingLeft) model.paddingLeft = pbModel.TextShape.PaddingLeft;
 077                    if (pbModel.TextShape.HasPaddingRight) model.paddingRight = pbModel.TextShape.PaddingRight;
 078                    if (pbModel.TextShape.HasPaddingTop) model.paddingTop = pbModel.TextShape.PaddingTop;
 079                    if (pbModel.TextShape.HasShadowBlur) model.shadowBlur = pbModel.TextShape.ShadowBlur;
 080                    if (pbModel.TextShape.ShadowColor != null) model.shadowColor = pbModel.TextShape.ShadowColor.AsUnity
 081                    if (pbModel.TextShape.HasShadowOffsetX) model.shadowOffsetX = pbModel.TextShape.ShadowOffsetX;
 082                    if (pbModel.TextShape.HasShadowOffsetY) model.shadowOffsetY = pbModel.TextShape.ShadowOffsetY;
 083                    if (pbModel.TextShape.HasTextWrapping) model.textWrapping = pbModel.TextShape.TextWrapping;
 084                    if (pbModel.TextShape.HasVTextAlign) model.vTextAlign = pbModel.TextShape.VTextAlign;
 085                    if (pbModel.TextShape.HasHTextAlign) model.hTextAlign = pbModel.TextShape.HTextAlign;
 086                    if (pbModel.TextShape.HasFontSize) model.fontAutoSize = pbModel.TextShape.FontSize == 0;
 087                    if (pbModel.TextShape.HasFontSize) model.fontSize = pbModel.TextShape.FontSize;
 88                    // if (pbModel.TextShape.HasLineSpacing) model.lineSpacing = float.Parse(pbModel.TextShape.LineSpaci
 089                }
 90                catch (Exception e)
 91                {
 092                    Debug.LogException(e);
 093                }
 94
 095                return model;
 96            }
 97
 98        }
 99
 100        public MeshRenderer meshRenderer;
 101        public TextMeshPro text;
 102        public RectTransform rectTransform;
 103        private Model cachedModel;
 104        private Material cachedFontMaterial;
 105        private Camera mainCamera;
 106        private bool cameraFound;
 107
 4108        public override string componentName => "text";
 109
 110        private bool CameraFound
 111        {
 112            get
 113            {
 0114                if (!cameraFound)
 115                {
 0116                    mainCamera = Camera.main;
 0117                    if (mainCamera != null)
 0118                        cameraFound = true;
 119                }
 120
 0121                return cameraFound;
 122            }
 123        }
 124
 125        private void Awake()
 126        {
 318127            model = new Model();
 128
 318129            cachedFontMaterial = new Material(text.fontSharedMaterial);
 130
 318131            text.fontSharedMaterial = cachedFontMaterial;
 318132            text.text = string.Empty;
 133
 318134            Environment.i.platform.updateEventHandler.AddListener(IUpdateEventHandler.EventType.Update, LookToCamera);
 318135        }
 136
 137        private void LookToCamera()
 138        {
 139            // Cameras are not detected while loading, so we can not load the camera on Awake or Start
 12088140            if (cachedModel is { billboard: true } && CameraFound)
 0141                transform.forward = mainCamera.transform.forward;
 12088142        }
 143
 144        public new Model GetModel() =>
 17145            cachedModel;
 146
 147        public override IEnumerator ApplyChanges(BaseModel newModel)
 148        {
 15149            if (rectTransform == null)
 0150                yield break;
 151
 15152            Model model = (Model)newModel;
 15153            cachedModel = model;
 15154            PrepareRectTransform();
 155
 156            // We avoid using even yield break; as this instruction skips a frame and we don't want that.
 15157            if (!DCLFont.IsFontLoaded(scene, model.font))
 158            {
 0159                yield return DCLFont.WaitUntilFontIsReady(scene, model.font);
 160            }
 161
 15162            DCLFont.SetFontFromComponent(scene, model.font, text);
 163
 15164            ApplyModelChanges(text, model);
 165
 15166            if (entity.meshRootGameObject == null)
 167            {
 11168                entity.meshesInfo.meshRootGameObject = gameObject;
 11169                entity.meshesInfo.RootIsPoolableObject = true;
 170            }
 171
 15172            entity.OnShapeUpdated?.Invoke(entity);
 15173        }
 174
 175        private static void ApplyModelChanges(TMP_Text text, Model model)
 176        {
 15177            text.text = model.value;
 178
 15179            text.color = new Color(model.color.r, model.color.g, model.color.b, model.visible ? model.opacity : 0);
 15180            text.fontSize = (int)model.fontSize;
 15181            text.richText = true;
 15182            text.overflowMode = TextOverflowModes.Overflow;
 15183            text.enableAutoSizing = model.fontAutoSize;
 184
 15185            text.margin =
 186                new Vector4
 187                (
 188                    (int)model.paddingLeft,
 189                    (int)model.paddingTop,
 190                    (int)model.paddingRight,
 191                    (int)model.paddingBottom
 192                );
 193
 15194            text.alignment = GetAlignment(model.vTextAlign, model.hTextAlign);
 15195            text.lineSpacing = model.lineSpacing;
 196
 15197            if (model.lineCount != 0)
 198            {
 1199                text.maxVisibleLines = Mathf.Max(model.lineCount, 1);
 200            }
 201            else
 202            {
 14203                text.maxVisibleLines = int.MaxValue;
 204            }
 205
 15206            text.enableWordWrapping = model.textWrapping && !text.enableAutoSizing;
 207
 15208            if (model.shadowOffsetX != 0 || model.shadowOffsetY != 0)
 209            {
 0210                text.fontSharedMaterial.EnableKeyword("UNDERLAY_ON");
 0211                text.fontSharedMaterial.SetColor("_UnderlayColor", model.shadowColor);
 0212                text.fontSharedMaterial.SetFloat("_UnderlaySoftness", model.shadowBlur);
 213            }
 15214            else if (text.fontSharedMaterial.IsKeywordEnabled("UNDERLAY_ON"))
 215            {
 0216                text.fontSharedMaterial.DisableKeyword("UNDERLAY_ON");
 217            }
 218
 15219            if (model.outlineWidth > 0f)
 220            {
 0221                text.fontSharedMaterial.EnableKeyword("OUTLINE_ON");
 0222                text.outlineWidth = model.outlineWidth;
 0223                text.outlineColor = model.outlineColor;
 224            }
 15225            else if (text.fontSharedMaterial.IsKeywordEnabled("OUTLINE_ON"))
 226            {
 0227                text.fontSharedMaterial.DisableKeyword("OUTLINE_ON");
 228            }
 15229        }
 230
 231        public static TextAlignmentOptions GetAlignment(string vTextAlign, string hTextAlign)
 232        {
 44233            vTextAlign = vTextAlign.ToLower();
 44234            hTextAlign = hTextAlign.ToLower();
 235
 44236            return vTextAlign switch
 237                   {
 3238                       "top" => hTextAlign switch
 239                                {
 1240                                    "left" => TextAlignmentOptions.TopLeft,
 1241                                    "right" => TextAlignmentOptions.TopRight,
 1242                                    _ => TextAlignmentOptions.Top
 243                                },
 3244                       "bottom" => hTextAlign switch
 245                                   {
 1246                                       "left" => TextAlignmentOptions.BottomLeft,
 1247                                       "right" => TextAlignmentOptions.BottomRight,
 1248                                       _ => TextAlignmentOptions.Bottom
 249                                   },
 38250                       _ => hTextAlign switch
 251                            {
 1252                                "left" => TextAlignmentOptions.Left,
 1253                                "right" => TextAlignmentOptions.Right,
 36254                                _ => TextAlignmentOptions.Center
 255                            }
 256                   };
 257        }
 258
 259        private void PrepareRectTransform()
 260        {
 15261            rectTransform.anchorMin = Vector2.zero;
 15262            rectTransform.anchorMax = Vector2.one;
 15263            rectTransform.offsetMin = Vector2.zero;
 15264            rectTransform.offsetMax = Vector2.zero;
 265
 266            // NOTE: previously width and height weren't working (setting sizeDelta before anchors and offset result in
 267            // sizeDelta being reset to 0,0)
 268            // to fix textWrapping and avoid backwards compatibility issues as result of the size being properly set (li
 269            // we only set it if textWrapping is enabled.
 15270            if (cachedModel.textWrapping)
 271            {
 0272                rectTransform.sizeDelta = new Vector2(cachedModel.width, cachedModel.height);
 273            }
 274            else
 275            {
 15276                rectTransform.sizeDelta = Vector2.zero;
 277            }
 15278        }
 279
 280        public override int GetClassId() =>
 1281            (int)CLASS_ID_COMPONENT.TEXT_SHAPE;
 282
 283        public override void Cleanup()
 284        {
 26285            text.text = string.Empty;
 26286            base.Cleanup();
 26287        }
 288
 289        private void OnDestroy()
 290        {
 318291            Environment.i.platform.updateEventHandler?.RemoveListener(IUpdateEventHandler.EventType.Update, LookToCamera
 292
 318293            base.Cleanup();
 318294            Destroy(cachedFontMaterial);
 318295        }
 296    }
 297}