using UnityEngine; using UnityEngine.TestTools; using NUnit.Framework; using System.Collections; using UnityEngine.UI; using System.Reflection; public class ImageTests { private const int Width = 32; private const int Height = 32; GameObject m_CanvasGO; TestableImage m_Image; private Texture2D m_DefaultTexture; private static SecondarySpriteTexture [] s_EmptySecondaryTexArray = {}; private bool m_dirtyLayout; private bool m_dirtyMaterial; [SetUp] public void SetUp() { m_CanvasGO = new GameObject("Canvas", typeof(Canvas)); GameObject imageObject = new GameObject("Image", typeof(TestableImage)); imageObject.transform.SetParent(m_CanvasGO.transform); m_Image = imageObject.GetComponent(); m_Image.RegisterDirtyLayoutCallback(() => m_dirtyLayout = true); m_Image.RegisterDirtyMaterialCallback(() => m_dirtyMaterial = true); m_DefaultTexture = CreateTexture(Color.magenta); } Texture2D CreateTexture(Color color) { var tex = new Texture2D(Width, Height); Color[] colors = new Color[Width * Height]; for (int i = 0; i < Width * Height; i++) colors[i] = color; tex.SetPixels(colors); tex.Apply(); return tex; } [Test] public void TightMeshSpritePopulatedVertexHelperProperly() { Texture2D texture = new Texture2D(64, 64); m_Image.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0, 0)); m_Image.type = Image.Type.Simple; m_Image.useSpriteMesh = true; VertexHelper vh = new VertexHelper(); m_Image.GenerateImageData(vh); Assert.AreEqual(vh.currentVertCount, m_Image.sprite.vertices.Length); Assert.AreEqual(vh.currentIndexCount, m_Image.sprite.triangles.Length); } [UnityTest] public IEnumerator CanvasCustomRefPixPerUnitToggleWillUpdateImageMesh() { var canvas = m_CanvasGO.GetComponent(); var canvasScaler = m_CanvasGO.AddComponent(); canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; m_Image.transform.SetParent(m_CanvasGO.transform); m_Image.type = Image.Type.Sliced; var texture = new Texture2D(120, 120); m_Image.sprite = Sprite.Create(texture, new Rect(0, 0, 120, 120), new Vector2(0.5f, 0.5f), 100, 1, SpriteMeshType.Tight, new Vector4(30, 30, 30, 30), true); m_Image.fillCenter = true; canvasScaler.referencePixelsPerUnit = 200; yield return null; // skip frame to update canvas properly //setup done canvas.enabled = false; yield return null; canvas.enabled = true; m_Image.isOnPopulateMeshCalled = false; yield return null; Assert.IsTrue(m_Image.isOnPopulateMeshCalled); } [UnityTest] public IEnumerator Sprite_Layout() { m_Image.sprite = Sprite.Create(m_DefaultTexture, new Rect(0, 0, Width, Height), Vector2.zero); yield return null; m_Image.isGeometryUpdated = false; m_dirtyLayout = false; var Texture = new Texture2D(Width * 2, Height * 2); m_Image.sprite = Sprite.Create(Texture, new Rect(0, 0, Width, Height), Vector2.zero); yield return new WaitUntil(() => m_Image.isGeometryUpdated); // validate that layout change rebuil is not called Assert.IsFalse(m_dirtyLayout); m_Image.isGeometryUpdated = false; m_dirtyLayout = false; m_Image.sprite = Sprite.Create(Texture, new Rect(0, 0, Width / 2, Height / 2), Vector2.zero); yield return new WaitUntil(() => m_Image.isGeometryUpdated); // validate that layout change rebuil is called Assert.IsTrue(m_dirtyLayout); } [UnityTest] public IEnumerator Sprite_Material() { m_Image.sprite = Sprite.Create(m_DefaultTexture, new Rect(0, 0, Width, Height), Vector2.zero); yield return null; m_Image.isGeometryUpdated = false; m_dirtyMaterial = false; m_Image.sprite = Sprite.Create(m_DefaultTexture, new Rect(0, 0, Width / 2, Height / 2), Vector2.zero); yield return new WaitUntil(() => m_Image.isGeometryUpdated); // validate that material change rebuild is not called Assert.IsFalse(m_dirtyMaterial); m_Image.isGeometryUpdated = false; m_dirtyMaterial = false; var Texture = new Texture2D(Width * 2, Height * 2); m_Image.sprite = Sprite.Create(Texture, new Rect(0, 0, Width / 2, Height / 2), Vector2.zero); yield return new WaitUntil(() => m_Image.isGeometryUpdated); // validate that layout change rebuil is called Assert.IsTrue(m_dirtyMaterial); } IEnumerator ValidateSecondaryTextures(SecondarySpriteTexture[] expectedSecondaryTextures) { yield return new WaitUntil(() => m_Image.isMaterialUpdated); if (expectedSecondaryTextures.Length == 0) Assert.Null(m_Image.secondaryTextures); else { Assert.NotNull(m_Image.secondaryTextures); Assert.AreEqual(expectedSecondaryTextures.Length, m_Image.secondaryTextures.Length); } Assert.AreEqual(expectedSecondaryTextures.Length, m_Image.canvasRenderer.GetSecondaryTextureCount()); for (int i = 0; i < expectedSecondaryTextures.Length; ++i) { Assert.AreEqual(expectedSecondaryTextures[i].name, m_Image.secondaryTextures[i].name); Assert.AreEqual(expectedSecondaryTextures[i].texture, m_Image.secondaryTextures[i].texture); // Canvas Renderer Assert.AreEqual(expectedSecondaryTextures[i].name, m_Image.canvasRenderer.GetSecondaryTextureName(i)); Assert.AreEqual(expectedSecondaryTextures[i].texture, m_Image.canvasRenderer.GetSecondaryTexture(i)); } } [UnityTest] public IEnumerator Sprite_NoSecondaryTextures() { var sprite = Sprite.Create(m_DefaultTexture, new Rect(0, 0, Width, Height), Vector2.zero); m_dirtyMaterial = false; m_Image.isMaterialUpdated = false; m_Image.sprite = sprite; Assert.IsTrue(m_dirtyMaterial); yield return ValidateSecondaryTextures(s_EmptySecondaryTexArray); } [UnityTest] public IEnumerator Sprite_SecondaryTextures() { var secondaryTextures = new[] { new SecondarySpriteTexture() { name = "_MaskTex", texture = CreateTexture(Color.red) }, new SecondarySpriteTexture() { name = "_GlowTex", texture = CreateTexture(Color.yellow) } }; var sprite = Sprite.Create(m_DefaultTexture, new Rect(0, 0, Width, Height), Vector2.zero, 100, 0, SpriteMeshType.FullRect, Vector4.zero, false, secondaryTextures); m_dirtyMaterial = false; m_Image.isMaterialUpdated = false; m_Image.sprite = sprite; Assert.IsTrue(m_dirtyMaterial); yield return ValidateSecondaryTextures(secondaryTextures); } [UnityTest] public IEnumerator Sprite_SecondaryTexturesUpdatedAfterSpriteChanged() { var spriteWithNoSecTex = Sprite.Create(m_DefaultTexture, new Rect(0, 0, Width, Height), Vector2.zero); m_dirtyMaterial = false; m_Image.isMaterialUpdated = false; m_Image.sprite = spriteWithNoSecTex; Assert.IsTrue(m_dirtyMaterial); yield return ValidateSecondaryTextures(s_EmptySecondaryTexArray); var twoSecondaryTextures = new[] { new SecondarySpriteTexture() { name = "_MaskTex", texture = CreateTexture(Color.red) }, new SecondarySpriteTexture() { name = "_GlowTex", texture = CreateTexture(Color.yellow) } }; var spriteWithTwoSecTexs = Sprite.Create(m_DefaultTexture, new Rect(0, 0, Width, Height), Vector2.zero, 100, 0, SpriteMeshType.FullRect, Vector4.zero, false, twoSecondaryTextures); m_dirtyMaterial = false; m_Image.isMaterialUpdated = false; m_Image.sprite = spriteWithTwoSecTexs; Assert.IsTrue(m_dirtyMaterial); yield return ValidateSecondaryTextures(twoSecondaryTextures); var oneSecondaryTexture = new[] { new SecondarySpriteTexture() { name = "_MaskTex", texture = CreateTexture(Color.red) } }; var spriteWithOneSecTex = Sprite.Create(m_DefaultTexture, new Rect(0, 0, Width, Height), Vector2.zero, 100, 0, SpriteMeshType.FullRect, Vector4.zero, false, oneSecondaryTexture); m_dirtyMaterial = false; m_Image.isMaterialUpdated = false; m_Image.sprite = spriteWithOneSecTex; Assert.IsTrue(m_dirtyMaterial); yield return ValidateSecondaryTextures(oneSecondaryTexture); m_Image.isMaterialUpdated = false; m_Image.sprite = spriteWithNoSecTex; Assert.IsTrue(m_dirtyMaterial); yield return ValidateSecondaryTextures(s_EmptySecondaryTexArray); } [TearDown] public void TearDown() { GameObject.DestroyImmediate(m_CanvasGO); GameObject.DestroyImmediate(m_DefaultTexture); } }