using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Sprites; using UnityEngine.UI; namespace EnergyBarToolkit { public class Image2 : MaskableGraphic { private class Quad { public enum Point { TopLeft = 0, TopRight = 1, BottomRight = 2, BottomLeft = 3 } public Point anchor; public float offset; public float progress; public bool invert; public Quad(bool invert) { this.invert = invert; } public Quad(Quad other) { anchor = other.anchor; offset = other.offset; progress = other.progress; invert = other.invert; } public MadList Points(float left, float top, float right, float bottom, MadList list) { list.Clear(); if (progress == 0f) { return list; } if (progress == 1f) { list.Add(new Vector2(left, bottom)); list.Add(new Vector2(left, top)); list.Add(new Vector2(right, top)); list.Add(new Vector2(right, bottom)); } else { float num = Y(progress + offset); float num2 = left + (right - left) * num; float num3 = bottom + (top - bottom) * num; float num4 = offset + progress; float num5 = Y(offset); float num6 = left + (right - left) * num5; float num7 = bottom + (top - bottom) * num5; switch (anchor) { case Point.BottomLeft: if (!invert) { if (num4 < 0.5f) { list.Add(new Vector2(left, bottom)); list.Add(new Vector2(num6, top)); list.Add(new Vector2(num2, top)); list.Add(new Vector2(num2, top)); } else if (offset < 0.5f) { list.Add(new Vector2(left, bottom)); list.Add(new Vector2(num6, top)); list.Add(new Vector2(right, top)); list.Add(new Vector2(right, num3)); } else { list.Add(new Vector2(left, bottom)); list.Add(new Vector2(right, num7)); list.Add(new Vector2(right, num3)); list.Add(new Vector2(right, num3)); } } else if (num4 < 0.5f) { list.Add(new Vector2(left, bottom)); list.Add(new Vector2(right, num7)); list.Add(new Vector2(right, num3)); list.Add(new Vector2(right, num3)); } else if (offset < 0.5f) { list.Add(new Vector2(left, bottom)); list.Add(new Vector2(right, num7)); list.Add(new Vector2(right, top)); list.Add(new Vector2(num2, top)); } else { list.Add(new Vector2(left, bottom)); list.Add(new Vector2(num6, top)); list.Add(new Vector2(num2, top)); list.Add(new Vector2(num2, top)); } break; case Point.TopLeft: if (!invert) { if (num4 < 0.5f) { list.Add(new Vector2(left, top)); list.Add(new Vector2(right, top - num7)); list.Add(new Vector2(right, top - num3)); list.Add(new Vector2(right, top - num3)); } else if (offset < 0.5f) { list.Add(new Vector2(left, top)); list.Add(new Vector2(right, top - num7)); list.Add(new Vector2(right, bottom)); list.Add(new Vector2(num2, bottom)); } else { list.Add(new Vector2(left, top)); list.Add(new Vector2(num6, bottom)); list.Add(new Vector2(num2, bottom)); list.Add(new Vector2(num2, bottom)); } } else if (num4 < 0.5f) { list.Add(new Vector2(left, top)); list.Add(new Vector2(num6, bottom)); list.Add(new Vector2(num2, bottom)); list.Add(new Vector2(num2, bottom)); } else if (offset < 0.5f) { list.Add(new Vector2(left, top)); list.Add(new Vector2(num6, bottom)); list.Add(new Vector2(right, bottom)); list.Add(new Vector2(right, top - num3)); } else { list.Add(new Vector2(left, top)); list.Add(new Vector2(right, top - num7)); list.Add(new Vector2(right, top - num3)); list.Add(new Vector2(right, top - num3)); } break; case Point.TopRight: if (!invert) { if (num4 < 0.5f) { list.Add(new Vector2(right, top)); list.Add(new Vector2(right - num6, bottom)); list.Add(new Vector2(right - num2, bottom)); list.Add(new Vector2(right - num2, bottom)); } else if (offset < 0.5f) { list.Add(new Vector2(right, top)); list.Add(new Vector2(right - num6, bottom)); list.Add(new Vector2(left, bottom)); list.Add(new Vector2(left, top - num3)); } else { list.Add(new Vector2(right, top)); list.Add(new Vector2(left, top - num7)); list.Add(new Vector2(left, top - num3)); list.Add(new Vector2(left, top - num3)); } } else if (num4 < 0.5f) { list.Add(new Vector2(right, top)); list.Add(new Vector2(left, top - num7)); list.Add(new Vector2(left, top - num3)); list.Add(new Vector2(left, top - num3)); } else if (offset < 0.5f) { list.Add(new Vector2(right, top)); list.Add(new Vector2(left, top - num7)); list.Add(new Vector2(left, bottom)); list.Add(new Vector2(right - num2, bottom)); } else { list.Add(new Vector2(right, top)); list.Add(new Vector2(right - num6, bottom)); list.Add(new Vector2(right - num2, bottom)); list.Add(new Vector2(right - num2, bottom)); } break; case Point.BottomRight: if (!invert) { if (num4 < 0.5f) { list.Add(new Vector2(right, bottom)); list.Add(new Vector2(left, num7)); list.Add(new Vector2(left, num3)); list.Add(new Vector2(left, num3)); } else if (offset < 0.5f) { list.Add(new Vector2(right, bottom)); list.Add(new Vector2(left, num7)); list.Add(new Vector2(left, top)); list.Add(new Vector2(right - num2, top)); } else { list.Add(new Vector2(right, bottom)); list.Add(new Vector2(right - num6, top)); list.Add(new Vector2(right - num2, top)); list.Add(new Vector2(right - num2, top)); } } else if (num4 < 0.5f) { list.Add(new Vector2(right, bottom)); list.Add(new Vector2(right - num6, top)); list.Add(new Vector2(right - num2, top)); list.Add(new Vector2(right - num2, top)); } else if (offset < 0.5f) { list.Add(new Vector2(right, bottom)); list.Add(new Vector2(right - num6, top)); list.Add(new Vector2(left, top)); list.Add(new Vector2(left, num3)); } else { list.Add(new Vector2(right, bottom)); list.Add(new Vector2(left, num7)); list.Add(new Vector2(left, num3)); list.Add(new Vector2(left, num3)); } break; default: Debug.LogError("Unknown anchor: " + anchor); break; } } return list; } private float Y(float val) { float num = 1f; float num2 = ((!(val < 0.5f)) ? (1f - val) : val); float f = num2 * 90f * ((float)Math.PI / 180f); return Mathf.Tan(f) * num; } } public Sprite sprite; [SerializeField] private Sprite cachedSprite; [SerializeField] private Vector4 cachedPadding; private static Dictionary cachedPaddings = new Dictionary(); public EnergyBarBase.GrowDirection growDirection; [SerializeField] private float _fillValue = 1f; public float radialFillOffset; public float radialFillLength = 1f; public Vector2 uvOffset = Vector2.zero; public Vector2 uvTiling = Vector2.one; public bool readable; public float fillValue { get { return _fillValue; } set { _fillValue = value; SetVerticesDirty(); } } public override Texture mainTexture { get { if (sprite == null) { return Graphic.s_WhiteTexture; } return sprite.texture; } } protected override void OnPopulateMesh(Mesh mesh) { if (growDirection != EnergyBarBase.GrowDirection.RadialCW && growDirection != EnergyBarBase.GrowDirection.RadialCCW) { FillRegular(mesh); } else { FillQuad(mesh); } } private void FillRegular(Mesh mesh) { if (sprite == null) { return; } Vector4 drawingDimensions = GetDrawingDimensions(false); float x = drawingDimensions.x; float z = drawingDimensions.z; float y = drawingDimensions.y; float w = drawingDimensions.w; Vector2 zero = Vector2.zero; Vector2 zero2 = Vector2.zero; if (growDirection == EnergyBarBase.GrowDirection.ExpandHorizontal) { zero.x = Mathf.Lerp(0.5f, 0f, fillValue); zero2.x = Mathf.Lerp(0.5f, 1f, fillValue); } else { if (growDirection == EnergyBarBase.GrowDirection.RightToLeft) { zero.x = Mathf.Lerp(1f, 0f, fillValue); } else { zero.x = 0f; } if (growDirection == EnergyBarBase.GrowDirection.LeftToRight) { zero2.x = Mathf.Lerp(0f, 1f, fillValue); } else { zero2.x = 1f; } } if (growDirection == EnergyBarBase.GrowDirection.ExpandVertical) { zero2.y = Mathf.Lerp(0.5f, 1f, fillValue); zero.y = Mathf.Lerp(0.5f, 0f, fillValue); } else { if (growDirection == EnergyBarBase.GrowDirection.BottomToTop) { zero2.y = Mathf.Lerp(0f, 1f, fillValue); } else { zero2.y = 1f; } if (growDirection == EnergyBarBase.GrowDirection.TopToBottom) { zero.y = Mathf.Lerp(1f, 0f, fillValue); } else { zero.y = 0f; } } Vector4 outerUV = DataUtility.GetOuterUV(sprite); outerUV = FixUV(outerUV); float num = outerUV.z - outerUV.x; float num2 = outerUV.w - outerUV.y; Vector2 vector = new Vector2(outerUV.x + num * zero.x, outerUV.y + num2 * zero.y); Vector2 vector2 = new Vector2(outerUV.z - num * (1f - zero2.x), outerUV.w - num2 * (1f - zero2.y)); if (uvOffset != Vector2.zero) { vector.x += uvOffset.x; vector2.x += uvOffset.x; vector.y += uvOffset.y; vector2.y += uvOffset.y; } if (uvTiling != Vector2.one) { vector2.x = vector.x + (vector2.x - vector.x) * uvTiling.x; vector2.y = vector.y + (vector2.y - vector.y) * uvTiling.y; } zero.x *= z - x; zero.y *= w - y; zero2.x *= z - x; zero2.y *= w - y; zero.x += x; zero.y += y; zero2.x += x; zero2.y += y; using (VertexHelper vertexHelper = new VertexHelper()) { vertexHelper.AddVert(new Vector2(zero.x, zero.y), color, new Vector2(vector.x, vector.y)); vertexHelper.AddVert(new Vector2(zero.x, zero2.y), color, new Vector2(vector.x, vector2.y)); vertexHelper.AddVert(new Vector2(zero2.x, zero2.y), color, new Vector2(vector2.x, vector2.y)); vertexHelper.AddVert(new Vector2(zero2.x, zero.y), color, new Vector2(vector2.x, vector.y)); vertexHelper.AddTriangle(0, 1, 2); vertexHelper.AddTriangle(2, 3, 0); vertexHelper.FillMesh(mesh); } } private Vector4 FixUV(Vector4 outerUv) { if (Application.HasProLicense() || Application.unityVersion.StartsWith("5.")) { return outerUv; } if (sprite == null) { return outerUv; } Vector4 vector = GetCachedPadding(); float width = sprite.rect.width; float height = sprite.rect.height; outerUv.x += vector.x / width; outerUv.y += vector.y / height; outerUv.z -= vector.z / width; outerUv.w -= vector.w / height; return outerUv; } private void FillQuad(Mesh mesh) { bool flag = growDirection == EnergyBarBase.GrowDirection.RadialCCW; Quad quad = new Quad(flag); Quad quad2 = new Quad(flag); Quad quad3 = new Quad(flag); Quad quad4 = new Quad(flag); quad.anchor = Quad.Point.BottomRight; quad2.anchor = Quad.Point.BottomLeft; quad3.anchor = Quad.Point.TopLeft; quad4.anchor = Quad.Point.TopRight; Quad quad5 = new Quad(quad); Quad quad6 = new Quad(quad2); Quad quad7 = new Quad(quad3); Quad quad8 = new Quad(quad4); Quad[] array = new Quad[8]; if (!flag) { array[0] = quad2; array[1] = quad3; array[2] = quad4; array[3] = quad; array[4] = quad6; array[5] = quad7; array[6] = quad8; array[7] = quad5; } else { array[7] = quad6; array[6] = quad7; array[5] = quad8; array[4] = quad5; array[3] = quad2; array[2] = quad3; array[1] = quad4; array[0] = quad; } float num = radialFillOffset % 1f; if (num < 0f) { num += 1f; } float num2 = Mathf.Clamp01(fillValue) * radialFillLength; float num3 = num * 4f; float num4 = (num + num2) * 4f; for (int i = Mathf.FloorToInt(num3); i < Mathf.CeilToInt(num4); i++) { Quad quad9 = array[i % 8]; if ((float)i < num3) { quad9.offset = num3 - (float)i; } else { quad9.offset = 0f; } if (num4 > (float)(i + 1)) { quad9.progress = 1f - quad9.offset; } else { quad9.progress = num4 - (float)i - quad9.offset; } } float num5 = 1f; float num6 = 1f; float num7 = num5 / 2f; float num8 = num6 / 2f; MadList madList = new MadList(4); MadList uvs = new MadList(4); using (VertexHelper vertexHelper = new VertexHelper()) { Vector4 outerUV = DataUtility.GetOuterUV(sprite); outerUV = FixUV(outerUV); quad2.Points(num7, num6, num5, num8, madList); PreparePointsAndUvs(madList, uvs, outerUV); AddToMesh(vertexHelper, madList, uvs); quad6.Points(num7, num6, num5, num8, madList); PreparePointsAndUvs(madList, uvs, outerUV); AddToMesh(vertexHelper, madList, uvs); quad3.Points(num7, num8, num5, 0f, madList); PreparePointsAndUvs(madList, uvs, outerUV); AddToMesh(vertexHelper, madList, uvs); quad7.Points(num7, num8, num5, 0f, madList); PreparePointsAndUvs(madList, uvs, outerUV); AddToMesh(vertexHelper, madList, uvs); quad4.Points(0f, num8, num7, 0f, madList); PreparePointsAndUvs(madList, uvs, outerUV); AddToMesh(vertexHelper, madList, uvs); quad8.Points(0f, num8, num7, 0f, madList); PreparePointsAndUvs(madList, uvs, outerUV); AddToMesh(vertexHelper, madList, uvs); quad.Points(0f, num6, num7, num8, madList); PreparePointsAndUvs(madList, uvs, outerUV); AddToMesh(vertexHelper, madList, uvs); quad5.Points(0f, num6, num7, num8, madList); PreparePointsAndUvs(madList, uvs, outerUV); AddToMesh(vertexHelper, madList, uvs); vertexHelper.FillMesh(mesh); } } private void PreparePointsAndUvs(MadList points, MadList uvs, Vector4 outerUv) { uvs.Clear(); Vector4 drawingDimensions = GetDrawingDimensions(false); float x = drawingDimensions.x; float z = drawingDimensions.z; float y = drawingDimensions.y; float w = drawingDimensions.w; float num = z - x; float num2 = w - y; float num3 = outerUv.z - outerUv.x; float num4 = outerUv.w - outerUv.y; for (int i = 0; i < points.Count; i++) { Vector2 value = points[i]; Vector2 e = new Vector2(outerUv.x + num3 * value.x, outerUv.y + num4 * value.y); if (uvOffset != Vector2.zero) { e.x += uvOffset.x; e.y += uvOffset.y; } value.x *= num; value.y *= num2; value.x += x; value.y += y; points[i] = value; uvs.Add(e); } } private void AddToMesh(VertexHelper vertexHelper, MadList points, MadList uvs) { for (int i = 0; i < points.Count; i++) { Vector2 vector = points[i]; Vector2 vector2 = uvs[i]; vertexHelper.AddVert(vector, color, new Vector2(vector2.x, vector2.y)); } if (points.Count >= 4) { int num = vertexHelper.currentVertCount - 4; vertexHelper.AddTriangle(num, 1 + num, 2 + num); vertexHelper.AddTriangle(2 + num, 3 + num, num); } } public override void SetNativeSize() { if (!(sprite == null)) { int num = Mathf.RoundToInt(sprite.rect.width); int num2 = Mathf.RoundToInt(sprite.rect.height); base.rectTransform.anchorMax = base.rectTransform.anchorMin; base.rectTransform.sizeDelta = new Vector2(num, num2); SetAllDirty(); } } public Vector4 GetDrawingDimensions(bool shouldPreserveAspect) { Vector4 vector = GetCachedPadding(); Vector2 vector2 = ((sprite == null) ? Vector2.zero : new Vector2(sprite.rect.width, sprite.rect.height)); Rect pixelAdjustedRect = GetPixelAdjustedRect(); int num = Mathf.RoundToInt(vector2.x); int num2 = Mathf.RoundToInt(vector2.y); Vector4 vector3 = new Vector4(vector.x / (float)num, vector.y / (float)num2, ((float)num - vector.z) / (float)num, ((float)num2 - vector.w) / (float)num2); if (shouldPreserveAspect && (double)vector2.sqrMagnitude > 0.0) { float num3 = vector2.x / vector2.y; float num4 = pixelAdjustedRect.width / pixelAdjustedRect.height; if ((double)num3 > (double)num4) { float height = pixelAdjustedRect.height; pixelAdjustedRect.height = pixelAdjustedRect.width * (1f / num3); pixelAdjustedRect.y += (height - pixelAdjustedRect.height) * base.rectTransform.pivot.y; } else { float width = pixelAdjustedRect.width; pixelAdjustedRect.width = pixelAdjustedRect.height * num3; pixelAdjustedRect.x += (width - pixelAdjustedRect.width) * base.rectTransform.pivot.x; } } return new Vector4(pixelAdjustedRect.x + pixelAdjustedRect.width * vector3.x, pixelAdjustedRect.y + pixelAdjustedRect.height * vector3.y, pixelAdjustedRect.x + pixelAdjustedRect.width * vector3.z, pixelAdjustedRect.y + pixelAdjustedRect.height * vector3.w); } private Vector4 GetCachedPadding() { if (Application.HasProLicense() || !Application.unityVersion.StartsWith("4.")) { return DataUtility.GetPadding(sprite); } Vector4 padding; if (sprite != cachedSprite) { padding = GetPadding(sprite); cachedSprite = sprite; cachedPadding = padding; } else { padding = cachedPadding; } return padding; } private Vector4 GetPadding(Sprite sprite) { if (sprite == null) { return Vector4.zero; } if (Application.HasProLicense() || !Application.unityVersion.StartsWith("4.")) { return DataUtility.GetPadding(sprite); } int instanceID = sprite.texture.GetInstanceID(); if (cachedPaddings.ContainsKey(instanceID)) { return cachedPaddings[instanceID]; } Vector4 paddingManual = GetPaddingManual(sprite); cachedPaddings[instanceID] = paddingManual; return paddingManual; } private Vector4 GetPaddingManual(Sprite sprite) { if (!readable) { return Vector4.zero; } return Utils.ComputePadding(sprite.texture, sprite.rect); } } }