< Summary

Class:DCL.UIElements.Image.DCLImage
Assembly:ECS7.UIElements
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLPlugins/ECS7/UIElements/Image/DCLImage.cs
Covered lines:65
Uncovered lines:89
Coverable lines:154
Total lines:307
Line coverage:42.2% (65 of 154)
Covered branches:0
Total branches:0
Covered methods:23
Total methods:35
Method coverage:65.7% (23 of 35)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
DCLImage()0%110100%
DCLImage(...)0%110100%
DCLImage(...)0%110100%
Dispose()0%2100%
SetScaleMode(...)0%2.862040%
SetTexture(...)0%2.032080%
SetSlices(...)0%2.032080%
SetColor(...)0%2.032080%
SetUVs(...)0%2.032080%
ResolveGenerationWay()0%6.425061.54%
AdjustUVs()0%6200%
AdjustSlices()0%4.683042.86%
SetSliced()0%110100%
SetCentered()0%2100%
SetStretched()0%2100%
SetSolidColor()0%110100%
OnGenerateVisualContent(...)0%20400%
GenerateStretched(...)0%2100%
GenerateCenteredTexture(...)0%2100%
ApplyVerticesTint()0%6200%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/DCLPlugins/ECS7/UIElements/Image/DCLImage.cs

#LineLine coverage
 1using DCL.UIElements.Structures;
 2using UnityEngine;
 3using UnityEngine.UIElements;
 4
 5namespace DCL.UIElements.Image
 6{
 7    /// <summary>
 8    /// Draw an image on a canvas according to the custom logic
 9    /// </summary>
 10    public class DCLImage : IUITextureConsumer
 11    {
 112        private static readonly Vertex[] VERTICES = new Vertex[4];
 113        private static readonly ushort[] INDICES = { 0, 1, 2, 2, 3, 0 };
 14
 15        private DCLImageScaleMode scaleMode;
 16        private Texture2D texture2D;
 17        private Sprite sprite;
 18        private Vector4 slices;
 19        private Color color;
 20        private DCLUVs uvs;
 21
 2322        internal VisualElement canvas { get; private set; }
 423        internal bool customMeshGenerationRequired { get; private set; }
 24
 25        public DCLImageScaleMode ScaleMode
 26        {
 127            get => scaleMode;
 128            set => SetScaleMode(value);
 29        }
 30
 31        public Texture2D Texture
 32        {
 033            get => texture2D;
 134            set => SetTexture(value);
 35        }
 36
 37        /// <summary>
 38        /// Border in normalized values
 39        /// </summary>
 40        public Vector4 Slices
 41        {
 042            get => slices;
 143            set => SetSlices(value);
 44        }
 45
 46        public Color Color
 47        {
 048            get => color;
 149            set => SetColor(value);
 50        }
 51
 52        public DCLUVs UVs
 53        {
 054            get => uvs;
 155            set => SetUVs(value);
 56        }
 57
 1358        private IStyle style => canvas.style;
 59
 260        public DCLImage(VisualElement canvas) : this(canvas, null, default, Vector4.zero, new Color(1, 1, 1, 0), default
 61
 162        public DCLImage(VisualElement canvas, Texture2D texture2D, DCLImageScaleMode scaleMode, Vector4 slices, Color co
 63        {
 164            this.texture2D = texture2D;
 165            this.scaleMode = scaleMode;
 166            this.slices = slices;
 167            this.color = color;
 168            this.uvs = uvs;
 169            this.canvas = canvas;
 70
 171            canvas.generateVisualContent += OnGenerateVisualContent;
 172        }
 73
 74        public void Dispose()
 75        {
 076            canvas.generateVisualContent -= OnGenerateVisualContent;
 077        }
 78
 79        private void SetScaleMode(DCLImageScaleMode scaleMode)
 80        {
 181            if (this.scaleMode == scaleMode)
 182                return;
 83
 084            this.scaleMode = scaleMode;
 085            ResolveGenerationWay();
 086        }
 87
 88        private void SetTexture(Texture2D texture)
 89        {
 190            if (this.texture2D == texture)
 091                return;
 92
 193            this.texture2D = texture;
 194            ResolveGenerationWay();
 195        }
 96
 97        private void SetSlices(Vector4 slices)
 98        {
 199            if (this.slices == slices)
 0100                return;
 101
 1102            this.slices = slices;
 1103            ResolveGenerationWay();
 1104        }
 105
 106        private void SetColor(Color color)
 107        {
 1108            if (this.color == color)
 0109                return;
 110
 1111            this.color = color;
 1112            ResolveGenerationWay();
 1113        }
 114
 115        private void SetUVs(DCLUVs uvs)
 116        {
 1117            if (this.uvs.Equals(uvs))
 0118                return;
 119
 1120            this.uvs = uvs;
 1121            ResolveGenerationWay();
 1122        }
 123
 124        private void ResolveGenerationWay()
 125        {
 4126            if (texture2D != null)
 127            {
 1128                switch (scaleMode)
 129                {
 130                    case DCLImageScaleMode.CENTER:
 0131                        SetCentered();
 0132                        break;
 133                    case DCLImageScaleMode.STRETCH:
 0134                        AdjustUVs();
 0135                        SetStretched();
 0136                        break;
 137                    case DCLImageScaleMode.NINE_SLICES:
 1138                        AdjustSlices();
 1139                        SetSliced();
 1140                        break;
 141                }
 142            }
 3143            else SetSolidColor();
 144
 4145            canvas.MarkDirtyRepaint();
 4146        }
 147
 148        private void AdjustUVs()
 149        {
 150            // check uvs
 0151            if (uvs.Equals(default))
 0152                uvs = DCLUVs.Default;
 0153        }
 154
 155        private void AdjustSlices()
 156        {
 1157            if (slices[0] + slices[2] > 1f)
 158            {
 0159                slices[0] = Mathf.Min(1f, slices[0]);
 0160                slices[2] = 1f - slices[0];
 161            }
 162
 1163            if (slices[1] + slices[3] > 1f)
 164            {
 0165                slices[1] = Mathf.Min(1f, slices[1]);
 0166                slices[3] = 1f - slices[1];
 167            }
 1168        }
 169
 170        private void SetSliced()
 171        {
 172            // Instead of generating a sliced mesh manually pass it to the existing logic of background
 1173            style.backgroundImage = Background.FromTexture2D(texture2D);
 1174            style.unityBackgroundImageTintColor = new StyleColor(color);
 1175            style.backgroundColor = new StyleColor(StyleKeyword.None);
 176
 1177            var texWidth = texture2D.width;
 1178            var texHeight = texture2D.height;
 179
 180            // convert slices to absolute values
 1181            style.unitySliceLeft = new StyleInt((int)(slices[0] * texWidth));
 1182            style.unitySliceTop = new StyleInt((int)(slices[1] * texHeight));
 1183            style.unitySliceRight = new StyleInt((int)(slices[2] * texWidth));
 1184            style.unitySliceBottom = new StyleInt((int)(slices[3] * texHeight));
 1185            customMeshGenerationRequired = false;
 1186        }
 187
 188        private void SetCentered()
 189        {
 0190            style.backgroundImage = new StyleBackground(StyleKeyword.Null);
 0191            style.backgroundColor = new StyleColor(StyleKeyword.None);
 0192            customMeshGenerationRequired = true;
 0193        }
 194
 195        private void SetStretched()
 196        {
 0197            style.backgroundImage = new StyleBackground(StyleKeyword.Null);
 0198            style.backgroundColor = new StyleColor(StyleKeyword.None);
 0199            customMeshGenerationRequired = true;
 0200        }
 201
 202        private void SetSolidColor()
 203        {
 3204            style.backgroundImage = new StyleBackground(StyleKeyword.None);
 3205            style.backgroundColor = new StyleColor(color);
 3206            customMeshGenerationRequired = false;
 3207        }
 208
 209        private void OnGenerateVisualContent(MeshGenerationContext mgc)
 210        {
 0211            if (!customMeshGenerationRequired)
 0212                return;
 213
 0214            switch (scaleMode)
 215            {
 216                case DCLImageScaleMode.CENTER:
 0217                    GenerateCenteredTexture(mgc);
 0218                    break;
 219                case DCLImageScaleMode.STRETCH:
 0220                    GenerateStretched(mgc);
 221                    break;
 222            }
 0223        }
 224
 225        private void GenerateStretched(MeshGenerationContext mgc)
 226        {
 227            // in local coords
 0228            var r = canvas.contentRect;
 229
 0230            float left = 0;
 0231            float right = r.width;
 0232            float top = 0;
 0233            float bottom = r.height;
 234
 0235            VERTICES[0].position = new Vector3(left, bottom, Vertex.nearZ);
 0236            VERTICES[1].position = new Vector3(left, top, Vertex.nearZ);
 0237            VERTICES[2].position = new Vector3(right, top, Vertex.nearZ);
 0238            VERTICES[3].position = new Vector3(right, bottom, Vertex.nearZ);
 239
 0240            var mwd = mgc.Allocate(VERTICES.Length, INDICES.Length, texture2D);
 241
 242            // uv Rect [0;1] that was assigned by the Dynamic atlas by UI Toolkit
 0243            var uvRegion = mwd.uvRegion;
 244
 0245            VERTICES[0].uv = uvs.BottomLeft * uvRegion.size + uvRegion.min;
 0246            VERTICES[1].uv = uvs.TopLeft * uvRegion.size + uvRegion.min;
 0247            VERTICES[2].uv = uvs.TopRight * uvRegion.size + uvRegion.min;
 0248            VERTICES[3].uv = uvs.BottomRight * uvRegion.size + uvRegion.min;
 249
 0250            ApplyVerticesTint();
 251
 0252            mwd.SetAllVertices(VERTICES);
 0253            mwd.SetAllIndices(INDICES);
 0254        }
 255
 256        private void GenerateCenteredTexture(MeshGenerationContext mgc)
 257        {
 258            // in local coords
 0259            var r = canvas.contentRect;
 260
 0261            var panelScale = canvas.worldTransform.lossyScale;
 0262            float targetTextureWidth = texture2D.width * panelScale[0];
 0263            float targetTextureHeight = texture2D.height * panelScale[1];
 264
 265            // Remain the original center
 0266            var center = r.center;
 267
 0268            float width = Mathf.Min(r.width, targetTextureWidth);
 0269            float height = Mathf.Min(r.height, targetTextureHeight);
 270
 0271            float left = center.x - (width / 2f);
 0272            float right = center.x + (width / 2f);
 0273            float top = center.y - (height / 2f);
 0274            float bottom = center.y + (height / 2f);
 275
 0276            VERTICES[0].position = new Vector3(left, bottom, Vertex.nearZ);
 0277            VERTICES[1].position = new Vector3(left, top, Vertex.nearZ);
 0278            VERTICES[2].position = new Vector3(right, top, Vertex.nearZ);
 0279            VERTICES[3].position = new Vector3(right, bottom, Vertex.nearZ);
 280
 0281            var mwd = mgc.Allocate(VERTICES.Length, INDICES.Length, texture2D);
 282
 283            // uv Rect [0;1] that was assigned by the Dynamic atlas by UI Toolkit
 0284            var uvRegion = mwd.uvRegion;
 285
 286            // the texture should be cut off if it exceeds the parent rect
 0287            var uvsDisplacementX = (1 - width / targetTextureWidth) / 2f;
 0288            var uvsDisplacementY = (1 - height / targetTextureHeight) / 2f;
 289
 0290            VERTICES[0].uv = new Vector2(uvsDisplacementX, uvsDisplacementY) * uvRegion.size + uvRegion.min;
 0291            VERTICES[1].uv = new Vector2(uvsDisplacementX, 1 - uvsDisplacementY) * uvRegion.size + uvRegion.min;
 0292            VERTICES[2].uv = new Vector2(1 - uvsDisplacementX, 1 - uvsDisplacementY) * uvRegion.size + uvRegion.min;
 0293            VERTICES[3].uv = new Vector2(1 - uvsDisplacementX, uvsDisplacementY) * uvRegion.size + uvRegion.min;
 294
 0295            ApplyVerticesTint();
 296
 0297            mwd.SetAllVertices(VERTICES);
 0298            mwd.SetAllIndices(INDICES);
 0299        }
 300
 301        private void ApplyVerticesTint()
 302        {
 0303            for (var i = 0; i < VERTICES.Length; i++)
 0304                VERTICES[i].tint = color;
 0305        }
 306    }
 307}