Skip to content

Instantly share code, notes, and snippets.

@LokoSoloGames
Created May 31, 2023 03:09
Show Gist options
  • Save LokoSoloGames/03a5767817ecfcc0c965d6a00c7b59b6 to your computer and use it in GitHub Desktop.
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
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