285 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			285 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | 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<TestableImage>(); | ||
|  |         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<Canvas>(); | ||
|  |         var canvasScaler = m_CanvasGO.AddComponent<CanvasScaler>(); | ||
|  | 
 | ||
|  |         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); | ||
|  |     } | ||
|  | 
 | ||
|  |     //UUM-114080 Prevent a crash caused by calling DestroyImmediate on the default uGUI material | ||
|  |     [Test] | ||
|  |     public void DestroyImmediate_OnDefaultMaterial_LogError() | ||
|  |     { | ||
|  |         var defaultMaterial = m_Image.defaultMaterial; | ||
|  |         var name = defaultMaterial.name; | ||
|  |         Object.DestroyImmediate(defaultMaterial, true); | ||
|  | 
 | ||
|  |         LogAssert.Expect(LogType.Error, $"Destroying object \"{name}\" is not allowed at this time."); | ||
|  | 
 | ||
|  |         //This is to ensure that the cached default material pointer in native is still valid. | ||
|  |         Assert.That(m_Image.defaultMaterial.name, Is.EqualTo(name)); | ||
|  |     } | ||
|  | 
 | ||
|  |     [TearDown] | ||
|  |     public void TearDown() | ||
|  |     { | ||
|  |         GameObject.DestroyImmediate(m_CanvasGO); | ||
|  |         GameObject.DestroyImmediate(m_DefaultTexture); | ||
|  |     } | ||
|  | } |