Last active
August 17, 2020 06:32
-
-
Save 3XclusiVe/7712365684665cef1e8e91bedfe7977b to your computer and use it in GitHub Desktop.
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 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; | |
} | |
} |
Author
3XclusiVe
commented
Aug 15, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment