Skip to content

Instantly share code, notes, and snippets.

@3XclusiVe
Last active August 17, 2020 06:32
Show Gist options
  • Save 3XclusiVe/7712365684665cef1e8e91bedfe7977b to your computer and use it in GitHub Desktop.
Save 3XclusiVe/7712365684665cef1e8e91bedfe7977b to your computer and use it in GitHub Desktop.
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
public class UIHelperGizmoDrawer
{
#if UNITY_USE_UI_MARGINS_VIEWER
[DrawGizmo(GizmoType.Selected)]
static void DrawGizmoForMyScript(RectTransform rect, GizmoType gizmoType)
{
UIMarginsViewer.DrawGizmo();
}
#endif
}
/**
* Showing margins between two selected ui elements
* Showing sizes of selected ui elements
*/
class UIMarginsViewer
{
static readonly int TextSize = 14;
static readonly Color TextColor = Color.white;
static readonly Color LinesColor = Color.red;
static Object _firstSelected;
static Object _secondSelected;
public static void DrawGizmo()
{
OnDrawGizmos();
}
static void OnDrawGizmos()
{
_firstSelected = null;
_secondSelected = null;
for (int index = 0; index < Selection.objects.Length; index++) {
var obj = Selection.objects[index];
DrawRectTransformsAndSizes(obj);
if (index == 0) {
_firstSelected = obj;
}
if (index == 1) {
_secondSelected = obj;
}
if (index > 1) {
//not support selection more than 2
continue;
}
}
DrawMutualPositions(_firstSelected, _secondSelected);
}
static void DrawMutualPositions(Object firstSelected, Object secondSelected)
{
var t1 = (firstSelected as GameObject)?.transform;
if (t1 == null) {
return;
}
var t2 = (secondSelected as GameObject)?.transform;
if (t2 == null) {
return;
}
var rect1 = t1.GetComponent<RectTransform>();
var rect2 = t2.GetComponent<RectTransform>();
if (rect1 == null && rect2 == null) {
return;
}
var offsets = CalculateOffsets(rect1, rect2);
DrawOffsets(rect1, rect2, offsets);
}
static void DrawOffsets(RectTransform rect1, RectTransform rect2, Vector4 offsets)
{
DrawXOffsets(rect1, rect2, offsets);
DrawYOffsets(rect1, rect2, offsets);
}
static void DrawYOffsets(RectTransform rect1, RectTransform rect2, Vector4 offsets)
{
//top
var topCenter = new Vector2(rect1.rect.min.x + rect1.position.x + rect1.rect.width / 2,
rect1.rect.max.y + rect1.position.y);
//down
var downCenter = new Vector2(rect1.rect.min.x + rect1.position.x + rect1.rect.width / 2,
rect1.rect.min.y + rect1.position.y);
bool oneSign = (offsets.y * offsets.w) > 0;
if (oneSign) {
if (offsets.y < 0) {
var start = downCenter;
var end = rect2.rect.yMax + rect2.position.y;
var value = end - downCenter.y;
DrawYOffsetLineWithText(start, value);
} else {
var start = topCenter;
var end = rect2.rect.yMin + rect2.position.y;
var value = end - topCenter.y;
DrawYOffsetLineWithText(start, value);
}
} else {
DrawYOffsetLineWithText(topCenter, offsets.y);
DrawYOffsetLineWithText(downCenter, offsets.w);
}
}
static void DrawXOffsets(RectTransform rect1, RectTransform rect2, Vector4 offsets)
{
//left
var leftCenter = new Vector2(rect1.rect.min.x + rect1.position.x,
rect1.rect.min.y + rect1.position.y + rect1.rect.height / 2);
//right
var rightCenter = new Vector2(rect1.rect.max.x + rect1.position.x,
rect1.rect.min.y + rect1.position.y + rect1.rect.height / 2);
bool oneSign = (offsets.x * offsets.z) > 0;
if (oneSign) {
if (offsets.x < 0) {
var start = leftCenter;
var end = rect2.rect.xMax + rect2.position.x;
var value = end - leftCenter.x;
DrawXOffsetLineWithText(start, value);
} else {
var start = rightCenter;
var end = rect2.rect.xMin + rect2.position.x;
var value = end - rightCenter.x;
DrawXOffsetLineWithText(start, value);
}
} else {
DrawXOffsetLineWithText(leftCenter, offsets.x);
DrawXOffsetLineWithText(rightCenter, offsets.z);
}
}
static void DrawXOffsetLineWithText(Vector2 start, float value)
{
var absValue = Mathf.Abs(value);
if (Mathf.Approximately(absValue, 0)) {
return;
}
var end = new Vector2(start.x + value, start.y);
var center = new Vector2(start.x + value / 2, start.y);
;
var textHeight = TextSize;
var sizeTextContent = $"{absValue}";
var textCenter = new Vector2(center.x, center.y + textHeight * 2f);
DrawLine(start, end, 5, LinesColor);
//draw text back
var textLenght = sizeTextContent.Length;
var textStart = new Vector3(textCenter.x - textLenght * textHeight * 1.5f, textCenter.y, 0);
var textEnd = new Vector3(textCenter.x + textLenght * textHeight * 1.5f, textCenter.y, 0);
DrawLine(textStart, textEnd, textHeight * 2, LinesColor);
//draw text
DrawText(UnityEngine.GUI.skin, sizeTextContent, textCenter, TextColor, textHeight);
}
static void DrawYOffsetLineWithText(Vector2 start, float value)
{
var absValue = Mathf.Abs(value);
if (Mathf.Approximately(absValue, 0)) {
return;
}
var end = new Vector2(start.x, start.y + value);
var center = new Vector2(start.x, start.y + value / 2);
var textHeight = TextSize;
var sizeTextContent = $"{absValue}";
var textCenter = new Vector2(center.x, center.y);
DrawLine(start, end, 5, LinesColor);
//draw text back
var textLenght = sizeTextContent.Length;
var textStart = new Vector3(textCenter.x - textLenght * textHeight * 1.5f, textCenter.y, 0);
var textEnd = new Vector3(textCenter.x + textLenght * textHeight * 1.5f, textCenter.y, 0);
DrawLine(textStart, textEnd, textHeight * 2, LinesColor);
//draw text
DrawText(UnityEngine.GUI.skin, sizeTextContent, textCenter, TextColor, textHeight);
}
static void DrawRectTransformsAndSizes(Object obj)
{
var transform = (obj as GameObject)?.transform;
if (transform == null) {
return;
}
var rect = transform.GetComponent<RectTransform>();
if (rect == null) {
return;
}
DrawRect(rect);
var size = CalculateSize(rect);
DrawSizeText(rect, size);
}
static void DrawRect(RectTransform rect)
{
Vector3[] points = new Vector3[]
{
new Vector3(rect.rect.min.x + rect.position.x,
rect.rect.min.y + rect.position.y),
new Vector3(rect.rect.min.x + rect.position.x,
rect.rect.min.y + rect.position.y + rect.rect.height),
new Vector3(rect.rect.min.x + rect.position.x,
rect.rect.min.y + rect.position.y + rect.rect.height),
new Vector3(rect.rect.max.x + rect.position.x,
rect.rect.max.y + rect.position.y),
new Vector3(rect.rect.max.x + rect.position.x,
rect.rect.max.y + rect.position.y),
new Vector3(rect.rect.max.x + rect.position.x,
rect.rect.max.y + rect.position.y - rect.rect.height),
new Vector3(rect.rect.max.x + rect.position.x,
rect.rect.max.y + rect.position.y - rect.rect.height),
new Vector3(rect.rect.min.x + rect.position.x,
rect.rect.min.y + rect.position.y),
};
GizmosUtils.DrawLines(points, 10, LinesColor);
}
static void DrawSizeText(RectTransform rect, Vector2 size)
{
var rectCenter = new Vector2(rect.rect.center.x + rect.position.x, rect.rect.center.y + rect.position.y);
var textHeight = TextSize;
var sizeTextContent = $"{size.x}x{size.y}";
var offset = 1.5f * textHeight;
var textPosition = new Vector2(rectCenter.x, rectCenter.y - rect.rect.height / 2 - offset);
//draw text back
var textLenght = sizeTextContent.Length;
var textStart = new Vector3(textPosition.x - textLenght * textHeight * 1.5f, textPosition.y, 0);
var textEnd = new Vector3(textPosition.x + textLenght * textHeight * 1.5f, textPosition.y, 0);
DrawLine(textStart, textEnd, textHeight * 2, LinesColor);
//draw text
DrawText(UnityEngine.GUI.skin, sizeTextContent, textPosition, TextColor, textHeight);
}
#region Logic
static Vector4 CalculateOffsets(RectTransform rect1, RectTransform rect2)
{
var leftOffset = (rect2.rect.min.x + rect2.position.x) - (rect1.rect.min.x + rect1.position.x);
var rightOffset = (rect2.rect.max.x + rect2.position.x) - (rect1.rect.max.x + rect1.position.x);
var downOffset = (rect2.rect.min.y + rect2.position.y) - (rect1.rect.min.y + rect1.position.y);
var topOffset = (rect2.rect.max.y + rect2.position.y) - (rect1.rect.max.y + rect1.position.y);
return new Vector4(leftOffset, topOffset, rightOffset, downOffset);
}
static Vector2 CalculateSize(RectTransform rect)
{
var size = Vector2.zero;
size.x = rect.rect.width;
size.y = rect.rect.height;
return size;
}
#endregion
public static void DrawLine(Vector3 p1, Vector3 p2, float width = 1, Color? color = null)
{
var prevColor = Handles.color;
var useColor = Color.white;
if (color != null) {
Handles.color = color.Value;
useColor = color.Value;
}
Handles.DrawBezier(p1, p2, p1, p2, useColor, null, width);
Handles.color = prevColor;
}
public static void DrawLines(Vector3[] lineSegments, float width = 1, Color? color = null)
{
if (lineSegments.Length % 2 != 0) {
Debug.LogError("unexpected format");
return;
}
for (int line = 0; line < lineSegments.Length; line += 2) {
var p1 = lineSegments[line];
var p2 = lineSegments[line + 1];
DrawLine(p1, p2, width, color);
}
}
public static void DrawText(GUISkin guiSkin, string text, Vector3 position, Color? color = null, int fontSize = 0,
float yOffset = 0)
{
var prevSkin = GUI.skin;
if (guiSkin == null)
Debug.LogWarning("editor warning: guiSkin parameter is null");
else
GUI.skin = guiSkin;
GUIContent textContent = new GUIContent(text);
GUIStyle style = (guiSkin != null) ? new GUIStyle(guiSkin.GetStyle("Label")) : new GUIStyle();
if (color != null)
style.normal.textColor = (Color) color;
if (fontSize > 0)
style.fontSize = fontSize;
Vector2 textSize = style.CalcSize(textContent);
Vector3 screenPoint = Camera.current.WorldToScreenPoint(position);
// checks necessary to the text is not visible when the camera is pointed in the opposite direction relative to the object
if (screenPoint.z > 0)
{
var worldPosition = Camera.current.ScreenToWorldPoint(new Vector3(screenPoint.x - textSize.x * 0.5f,
screenPoint.y + textSize.y * 0.5f + yOffset, screenPoint.z));
UnityEditor.Handles.Label(worldPosition, textContent, style);
}
GUI.skin = prevSkin;
}
}
@3XclusiVe
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment