Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
An extension of UnityEngine.UI.MaskableGraphic that allows for the drawing of arbitrary meshes
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace Softdrink
{
// Adapted from https://www.hallgrimgames.com/blog/2018/11/25/custom-unity-ui-meshes
// with significant modifications to account for arbitrary meshes and UVs
public class MeshGraphic : MaskableGraphic
{
[TooltipAttribute("For best results, use a 2D mesh built on the XY plane, with UVs, scaled to fit a unit square.")]
public Mesh mesh = null;
[TooltipAttribute("A scalar multiplier applied to mesh Z thickness.")]
public float zThickness = 0f;
// Scaling factor that will be automatically calculated based on mesh vertices
// Will attempt to automatically long-edge fit the XY projection of the Mesh to the RectTransform area
private float scaleFactor = 1f;
[SerializeField]
[TooltipAttribute("A Texture to map to the Mesh. If the Mesh has no UVs, new UVs will be generated in the RectTransform space.")]
Texture _texture;
[TooltipAttribute("If enabled, the Mesh will be recalculated whenever the RectTransform dimensions change. This provides the most intuitive results, but can be performance intensive. \nIf disabled, you must call UpdateMesh() manually to resize the mesh when changing the RectTransform dimensions.")]
public bool autoUpdateMesh = true;
private Vector3 vertMax;
private Vector3 vertMin;
// Redraw element when texture changed in Inspector
public Texture texture
{
get
{
return _texture;
}
set
{
if (_texture == value)
return;
_texture = value;
SetVerticesDirty();
SetMaterialDirty();
}
}
// Use default white texture if nothing is specified
public override Texture mainTexture
{
get
{
return _texture == null ? s_WhiteTexture : _texture;
}
}
#if UNITY_EDITOR
protected override void OnValidate()
{
base.OnValidate();
CalcMeshScaleFactor();
SetVerticesDirty();
SetMaterialDirty();
}
#endif
// Calculate a scaling factor for the input mesh based
// on bounding box size of all vertices
void CalcMeshScaleFactor()
{
vertMax = new Vector3(Single.MinValue, Single.MinValue, Single.MinValue);
vertMin = new Vector3(Single.MaxValue, Single.MaxValue, Single.MaxValue);
for(int i = 0; i < mesh.vertices.Length; i++)
{
vertMax = Vector3.Max(vertMax, mesh.vertices[i]);
vertMin = Vector3.Min(vertMin, mesh.vertices[i]);
}
float xRange = Mathf.Abs(vertMax.x - vertMin.x);
float yRange = Mathf.Abs(vertMax.y - vertMin.y);
float maxRange = Mathf.Max(xRange, yRange);
if(maxRange != 0f) scaleFactor = 1.0f/maxRange;
else scaleFactor = 1.0f;
}
// Calculate a UV in RectTransform space by mapping the current vertex position relative
// to the min and max vertex positions of the entire mesh
Vector2 CalculateRectspaceUV(Vector3 vPos)
{
return new Vector2(Map(vPos.x, vertMin.x, vertMax.x, 0f, 1f), Map(vPos.y, vertMin.y, vertMax.y, 0f, 1f));
}
float Map(float x, float aMin, float aMax, float bMin, float bMax)
{
return (x - aMin) * (bMax - bMin) / (aMax - aMin) + bMin;
}
protected override void OnPopulateMesh(VertexHelper vh)
{
vh.Clear();
if(mesh == null) return;
bool hasUV = (mesh.uv != null && mesh.uv.Length > 0);
Vector3 scale = new Vector3(rectTransform.rect.width, rectTransform.rect.height, zThickness);
scale *= scaleFactor;
for(int i = 0; i < mesh.vertices.Length; i++)
{
if(hasUV) vh.AddVert(Vector3.Scale(mesh.vertices[i], scale), color, mesh.uv[i]);
else vh.AddVert(Vector3.Scale(mesh.vertices[i], scale), color, CalculateRectspaceUV(mesh.vertices[i]));
}
for(int j = 0; j < mesh.triangles.Length; j+= 3)
{
vh.AddTriangle(mesh.triangles[j], mesh.triangles[j+1], mesh.triangles[j+2]);
}
}
protected override void OnRectTransformDimensionsChange()
{
base.OnRectTransformDimensionsChange();
if(!autoUpdateMesh) return;
SetVerticesDirty();
SetMaterialDirty();
}
public void UpdateMesh()
{
SetVerticesDirty();
SetMaterialDirty();
}
}
}
@Softdrink117

This comment has been minimized.

Copy link
Owner Author

@Softdrink117 Softdrink117 commented Feb 1, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.