Created
May 31, 2023 03:09
-
-
Save LokoSoloGames/03a5767817ecfcc0c965d6a00c7b59b6 to your computer and use it in GitHub Desktop.
Unity UI Image that stretch sprite to fit in RectTransform in Simple Image Type with preserve aspect toggled
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine.Sprites; | |
namespace UnityEngine.UI { | |
public class PreserveAspectEnvelopImage : Image { | |
protected override void OnPopulateMesh(VertexHelper toFill) { | |
if (type == Type.Simple && !useSpriteMesh && preserveAspect) { | |
GenerateSimpleSprite(toFill); | |
} else { | |
base.OnPopulateMesh(toFill); | |
} | |
} | |
void GenerateSimpleSprite(VertexHelper vh) { | |
Vector4 v = GetDrawingDimensions(); | |
var activeSprite = overrideSprite; | |
var uv = (activeSprite != null) ? DataUtility.GetOuterUV(activeSprite) : Vector4.zero; | |
if (activeSprite) { | |
var size = activeSprite.rect.size; | |
var ratio = size.x / size.y; | |
var rectSize = new Vector2(v.z - v.x, v.w - v.y); | |
var rectRatio = rectSize.x / rectSize.y; | |
if (rectRatio > ratio) { | |
// Fixed Width | |
var multiplier = ratio / rectRatio; | |
var pivot = Mathf.Clamp(rectTransform.pivot.y, uv.y, uv.w); | |
uv.y = pivot - (pivot - uv.y) * multiplier; | |
uv.w = (uv.w - pivot) * multiplier + pivot; | |
} else if (rectRatio < ratio) { | |
// Fixed Height | |
var multiplier = rectRatio / ratio; | |
var pivot = Mathf.Clamp(rectTransform.pivot.x, uv.x, uv.z); | |
uv.x = pivot - (pivot - uv.x) * multiplier; | |
uv.z = (uv.z - pivot) * multiplier + pivot; | |
} | |
} | |
Color32 color32 = color; | |
vh.Clear(); | |
vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(uv.x, uv.y)); | |
vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(uv.x, uv.w)); | |
vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(uv.z, uv.w)); | |
vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(uv.z, uv.y)); | |
vh.AddTriangle(0, 1, 2); | |
vh.AddTriangle(2, 3, 0); | |
} | |
private Vector4 GetDrawingDimensions() { | |
var activeSprite = overrideSprite; | |
var padding = activeSprite == null ? Vector4.zero : DataUtility.GetPadding(activeSprite); | |
var size = activeSprite == null ? Vector2.zero : activeSprite.rect.size; | |
Rect r = GetPixelAdjustedRect(); | |
int spriteW = Mathf.RoundToInt(size.x); | |
int spriteH = Mathf.RoundToInt(size.y); | |
var v = new Vector4( | |
padding.x / spriteW, | |
padding.y / spriteH, | |
(spriteW - padding.z) / spriteW, | |
(spriteH - padding.w) / spriteH); | |
v = new Vector4( | |
r.x + r.width * v.x, | |
r.y + r.height * v.y, | |
r.x + r.width * v.z, | |
r.y + r.height * v.w | |
); | |
return v; | |
} | |
#if UNITY_EDITOR | |
static UnityEditor.MonoScript _script; | |
[UnityEditor.MenuItem("CONTEXT/Image/Replace as Preserve Aspect Envelop Image")] | |
static void ReplaceFromBuiltInImage(UnityEditor.MenuCommand command) { | |
if (!_script) { | |
var tmpGO = new GameObject("tempOBJ"); | |
var inst = tmpGO.AddComponent<PreserveAspectEnvelopImage>(); | |
_script = UnityEditor.MonoScript.FromMonoBehaviour(inst); | |
DestroyImmediate(tmpGO); | |
} | |
var go = ((Component)command.context).gameObject; | |
UnityEditor.Undo.RegisterCompleteObjectUndo(go, string.Format("Replace Image as Preserve Aspect Envelop Image in {0}", go.name)); | |
UnityEditor.SerializedObject so = new UnityEditor.SerializedObject(command.context); | |
UnityEditor.SerializedProperty scriptProperty = so.FindProperty("m_Script"); | |
so.Update(); | |
scriptProperty.objectReferenceValue = _script; | |
so.ApplyModifiedProperties(); | |
} | |
#endif | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment