< 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:0
Uncovered lines:154
Coverable lines:154
Total lines:308
Line coverage:0% (0 of 154)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
DCLImage()0%2100%
DCLImage(...)0%2100%
DCLImage(...)0%2100%
Dispose()0%2100%
SetScaleMode(...)0%6200%
SetTexture(...)0%6200%
SetSlices(...)0%6200%
SetColor(...)0%6200%
SetUVs(...)0%6200%
ResolveGenerationWay()0%30500%
AdjustUVs()0%6200%
AdjustSlices()0%12300%
SetSliced()0%2100%
SetCentered()0%2100%
SetStretched()0%2100%
SetSolidColor()0%2100%
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    {
 012        private static readonly Vertex[] VERTICES = new Vertex[4];
 013        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
 022        internal VisualElement canvas { get; private set; }
 23
 024        internal bool customMeshGenerationRequired { get; private set; }
 25
 26        public DCLImageScaleMode ScaleMode
 27        {
 028            get => scaleMode;
 029            set => SetScaleMode(value);
 30        }
 31
 32        public Texture2D Texture
 33        {
 034            get => texture2D;
 035            set => SetTexture(value);
 36        }
 37
 38        /// <summary>
 39        /// Border in normalized values
 40        /// </summary>
 41        public Vector4 Slices
 42        {
 043            get => slices;
 044            set => SetSlices(value);
 45        }
 46
 47        public Color Color
 48        {
 049            get => color;
 050            set => SetColor(value);
 51        }
 52
 53        public DCLUVs UVs
 54        {
 055            get => uvs;
 056            set => SetUVs(value);
 57        }
 58
 059        private IStyle style => canvas.style;
 60
 061        public DCLImage(VisualElement canvas) : this(canvas, null, default, Vector4.zero, new Color(1, 1, 1, 0), default
 62
 063        public DCLImage(VisualElement canvas, Texture2D texture2D, DCLImageScaleMode scaleMode, Vector4 slices, Color co
 64        {
 065            this.texture2D = texture2D;
 066            this.scaleMode = scaleMode;
 067            this.slices = slices;
 068            this.color = color;
 069            this.uvs = uvs;
 070            this.canvas = canvas;
 71
 072            canvas.generateVisualContent += OnGenerateVisualContent;
 073        }
 74
 75        public void Dispose()
 76        {
 077            canvas.generateVisualContent -= OnGenerateVisualContent;
 078        }
 79
 80        private void SetScaleMode(DCLImageScaleMode scaleMode)
 81        {
 082            if (this.scaleMode == scaleMode)
 083                return;
 84
 085            this.scaleMode = scaleMode;
 086            ResolveGenerationWay();
 087        }
 88
 89        private void SetTexture(Texture2D texture)
 90        {
 091            if (this.texture2D == texture)
 092                return;
 93
 094            this.texture2D = texture;
 095            ResolveGenerationWay();
 096        }
 97
 98        private void SetSlices(Vector4 slices)
 99        {
 0100            if (this.slices == slices)
 0101                return;
 102
 0103            this.slices = slices;
 0104            ResolveGenerationWay();
 0105        }
 106
 107        private void SetColor(Color color)
 108        {
 0109            if (this.color == color)
 0110                return;
 111
 0112            this.color = color;
 0113            ResolveGenerationWay();
 0114        }
 115
 116        private void SetUVs(DCLUVs uvs)
 117        {
 0118            if (this.uvs.Equals(uvs))
 0119                return;
 120
 0121            this.uvs = uvs;
 0122            ResolveGenerationWay();
 0123        }
 124
 125        private void ResolveGenerationWay()
 126        {
 0127            if (texture2D != null)
 128            {
 0129                switch (scaleMode)
 130                {
 131                    case DCLImageScaleMode.CENTER:
 0132                        SetCentered();
 0133                        break;
 134                    case DCLImageScaleMode.STRETCH:
 0135                        AdjustUVs();
 0136                        SetStretched();
 0137                        break;
 138                    case DCLImageScaleMode.NINE_SLICES:
 0139                        AdjustSlices();
 0140                        SetSliced();
 0141                        break;
 142                }
 143            }
 0144            else SetSolidColor();
 145
 0146            canvas.MarkDirtyRepaint();
 0147        }
 148
 149        private void AdjustUVs()
 150        {
 151            // check uvs
 0152            if (uvs.Equals(default))
 0153                uvs = DCLUVs.Default;
 0154        }
 155
 156        private void AdjustSlices()
 157        {
 0158            if (slices[0] + slices[2] > 1f)
 159            {
 0160                slices[0] = Mathf.Min(1f, slices[0]);
 0161                slices[2] = 1f - slices[0];
 162            }
 163
 0164            if (slices[1] + slices[3] > 1f)
 165            {
 0166                slices[1] = Mathf.Min(1f, slices[1]);
 0167                slices[3] = 1f - slices[1];
 168            }
 0169        }
 170
 171        private void SetSliced()
 172        {
 173            // Instead of generating a sliced mesh manually pass it to the existing logic of background
 0174            style.backgroundImage = Background.FromTexture2D(texture2D);
 0175            style.unityBackgroundImageTintColor = new StyleColor(color);
 0176            style.backgroundColor = new StyleColor(StyleKeyword.None);
 177
 0178            var texWidth = texture2D.width;
 0179            var texHeight = texture2D.height;
 180
 181            // convert slices to absolute values
 0182            style.unitySliceLeft = new StyleInt((int)(slices[0] * texWidth));
 0183            style.unitySliceTop = new StyleInt((int)(slices[1] * texHeight));
 0184            style.unitySliceRight = new StyleInt((int)(slices[2] * texWidth));
 0185            style.unitySliceBottom = new StyleInt((int)(slices[3] * texHeight));
 0186            customMeshGenerationRequired = false;
 0187        }
 188
 189        private void SetCentered()
 190        {
 0191            style.backgroundImage = new StyleBackground(StyleKeyword.Null);
 0192            style.backgroundColor = new StyleColor(StyleKeyword.None);
 0193            customMeshGenerationRequired = true;
 0194        }
 195
 196        private void SetStretched()
 197        {
 0198            style.backgroundImage = new StyleBackground(StyleKeyword.Null);
 0199            style.backgroundColor = new StyleColor(StyleKeyword.None);
 0200            customMeshGenerationRequired = true;
 0201        }
 202
 203        private void SetSolidColor()
 204        {
 0205            style.backgroundImage = new StyleBackground(StyleKeyword.None);
 0206            style.backgroundColor = new StyleColor(color);
 0207            customMeshGenerationRequired = false;
 0208        }
 209
 210        private void OnGenerateVisualContent(MeshGenerationContext mgc)
 211        {
 0212            if (!customMeshGenerationRequired)
 0213                return;
 214
 0215            switch (scaleMode)
 216            {
 217                case DCLImageScaleMode.CENTER:
 0218                    GenerateCenteredTexture(mgc);
 0219                    break;
 220                case DCLImageScaleMode.STRETCH:
 0221                    GenerateStretched(mgc);
 222                    break;
 223            }
 0224        }
 225
 226        private void GenerateStretched(MeshGenerationContext mgc)
 227        {
 228            // in local coords
 0229            var r = canvas.contentRect;
 230
 0231            float left = 0;
 0232            float right = r.width;
 0233            float top = 0;
 0234            float bottom = r.height;
 235
 0236            VERTICES[0].position = new Vector3(left, bottom, Vertex.nearZ);
 0237            VERTICES[1].position = new Vector3(left, top, Vertex.nearZ);
 0238            VERTICES[2].position = new Vector3(right, top, Vertex.nearZ);
 0239            VERTICES[3].position = new Vector3(right, bottom, Vertex.nearZ);
 240
 0241            var mwd = mgc.Allocate(VERTICES.Length, INDICES.Length, texture2D);
 242
 243            // uv Rect [0;1] that was assigned by the Dynamic atlas by UI Toolkit
 0244            var uvRegion = mwd.uvRegion;
 245
 0246            VERTICES[0].uv = uvs.BottomLeft * uvRegion.size + uvRegion.min;
 0247            VERTICES[1].uv = uvs.TopLeft * uvRegion.size + uvRegion.min;
 0248            VERTICES[2].uv = uvs.TopRight * uvRegion.size + uvRegion.min;
 0249            VERTICES[3].uv = uvs.BottomRight * uvRegion.size + uvRegion.min;
 250
 0251            ApplyVerticesTint();
 252
 0253            mwd.SetAllVertices(VERTICES);
 0254            mwd.SetAllIndices(INDICES);
 0255        }
 256
 257        private void GenerateCenteredTexture(MeshGenerationContext mgc)
 258        {
 259            // in local coords
 0260            var r = canvas.contentRect;
 261
 0262            var panelScale = canvas.worldTransform.lossyScale;
 0263            float targetTextureWidth = texture2D.width * panelScale[0];
 0264            float targetTextureHeight = texture2D.height * panelScale[1];
 265
 266            // Remain the original center
 0267            var center = r.center;
 268
 0269            float width = Mathf.Min(r.width, targetTextureWidth);
 0270            float height = Mathf.Min(r.height, targetTextureHeight);
 271
 0272            float left = center.x - (width / 2f);
 0273            float right = center.x + (width / 2f);
 0274            float top = center.y - (height / 2f);
 0275            float bottom = center.y + (height / 2f);
 276
 0277            VERTICES[0].position = new Vector3(left, bottom, Vertex.nearZ);
 0278            VERTICES[1].position = new Vector3(left, top, Vertex.nearZ);
 0279            VERTICES[2].position = new Vector3(right, top, Vertex.nearZ);
 0280            VERTICES[3].position = new Vector3(right, bottom, Vertex.nearZ);
 281
 0282            var mwd = mgc.Allocate(VERTICES.Length, INDICES.Length, texture2D);
 283
 284            // uv Rect [0;1] that was assigned by the Dynamic atlas by UI Toolkit
 0285            var uvRegion = mwd.uvRegion;
 286
 287            // the texture should be cut off if it exceeds the parent rect
 0288            var uvsDisplacementX = (1 - width / targetTextureWidth) / 2f;
 0289            var uvsDisplacementY = (1 - height / targetTextureHeight) / 2f;
 290
 0291            VERTICES[0].uv = new Vector2(uvsDisplacementX, uvsDisplacementY) * uvRegion.size + uvRegion.min;
 0292            VERTICES[1].uv = new Vector2(uvsDisplacementX, 1 - uvsDisplacementY) * uvRegion.size + uvRegion.min;
 0293            VERTICES[2].uv = new Vector2(1 - uvsDisplacementX, 1 - uvsDisplacementY) * uvRegion.size + uvRegion.min;
 0294            VERTICES[3].uv = new Vector2(1 - uvsDisplacementX, uvsDisplacementY) * uvRegion.size + uvRegion.min;
 295
 0296            ApplyVerticesTint();
 297
 0298            mwd.SetAllVertices(VERTICES);
 0299            mwd.SetAllIndices(INDICES);
 0300        }
 301
 302        private void ApplyVerticesTint()
 303        {
 0304            for (var i = 0; i < VERTICES.Length; i++)
 0305                VERTICES[i].tint = color;
 0306        }
 307    }
 308}