149 lines
5.6 KiB
C#
149 lines
5.6 KiB
C#
// ===============================================================================
|
|
// MeasureTool - Smart Scene Measurement & Analysis
|
|
//
|
|
// Creator: Scove
|
|
// Last Updated: 2024-05-08
|
|
// Version: 3.0
|
|
//
|
|
// Purpose:
|
|
// A professional measurement tool that visualizes distances between objects
|
|
// in the Scene View. Supports single distance, chain distance, and axis breakdown.
|
|
//
|
|
// Key Features:
|
|
// 1. Two-Point & Chain Mode: Select 2 or more objects to measure.
|
|
// 2. Axis Breakdown: Shows Delta X, Y, Z with Unity-standard colors.
|
|
// 3. Scene Overlay: On-screen toggle and settings directly in Scene View.
|
|
// 4. Readable UI: High-contrast labels with background for any lighting condition.
|
|
//
|
|
// How to Use:
|
|
// 1. Place in an 'Editor' folder.
|
|
// 2. Select 2 or more GameObjects in the Hierarchy.
|
|
// 3. Use the "MEASURE" overlay in the Scene View to toggle axis details.
|
|
// ===============================================================================
|
|
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Editor
|
|
{
|
|
[InitializeOnLoad]
|
|
public class MeasureTool
|
|
{
|
|
// Settings (Persisted via EditorPrefs)
|
|
private static bool IsEnabled = true;
|
|
private static bool ShowAxisBreakdown = true;
|
|
private static bool ShowTotalDistance = true;
|
|
|
|
static MeasureTool()
|
|
{
|
|
IsEnabled = EditorPrefs.GetBool("MeasureTool_Enabled", true);
|
|
ShowAxisBreakdown = EditorPrefs.GetBool("MeasureTool_Axis", true);
|
|
|
|
SceneView.duringSceneGui += OnSceneGUI;
|
|
}
|
|
|
|
private static void OnSceneGUI(SceneView view)
|
|
{
|
|
DrawOverlay(view);
|
|
|
|
if (!IsEnabled || Selection.transforms.Length < 2) return;
|
|
|
|
Transform[] selected = Selection.transforms;
|
|
|
|
// Draw measurement for each pair in the selection
|
|
for (int i = 0; i < selected.Length - 1; i++)
|
|
{
|
|
DrawDistance(selected[i].position, selected[i + 1].position);
|
|
}
|
|
}
|
|
|
|
private static void DrawDistance(Vector3 p1, Vector3 p2)
|
|
{
|
|
float distance = Vector3.Distance(p1, p2);
|
|
Vector3 midPoint = (p1 + p2) * 0.5f;
|
|
|
|
// 1. Draw the Main Dotted Line
|
|
Handles.color = Color.cyan;
|
|
Handles.DrawDottedLine(p1, p2, 4f);
|
|
|
|
// Draw small spheres at start/end points for clarity
|
|
Handles.SphereHandleCap(0, p1, Quaternion.identity, 0.1f, EventType.Repaint);
|
|
Handles.SphereHandleCap(0, p2, Quaternion.identity, 0.1f, EventType.Repaint);
|
|
|
|
// 2. Draw Main Label (Total Distance)
|
|
if (ShowTotalDistance)
|
|
{
|
|
GUIStyle labelStyle = GetLabelStyle(Color.white, new Color(0, 0, 0, 0.6f));
|
|
string labelText = $"Dist: {distance:F2}m";
|
|
Handles.Label(midPoint + (Vector3.up * 0.1f), labelText, labelStyle);
|
|
}
|
|
|
|
// 3. Draw Axis Breakdown (X, Y, Z Delta)
|
|
if (ShowAxisBreakdown)
|
|
{
|
|
Vector3 delta = new Vector3(Mathf.Abs(p1.x - p2.x), Mathf.Abs(p1.y - p2.y), Mathf.Abs(p1.z - p2.z));
|
|
|
|
// We only show axis delta if it's significant (> 0.01)
|
|
string axisText = "";
|
|
if (delta.x > 0.01f) axisText += $"<color=#FF5555>X: {delta.x:F2}</color> ";
|
|
if (delta.y > 0.01f) axisText += $"<color=#55FF55>Y: {delta.y:F2}</color> ";
|
|
if (delta.z > 0.01f) axisText += $"<color=#5555FF>Z: {delta.z:F2}</color>";
|
|
|
|
if (!string.IsNullOrEmpty(axisText))
|
|
{
|
|
GUIStyle axisStyle = GetLabelStyle(Color.white, new Color(0.1f, 0.1f, 0.1f, 0.8f));
|
|
axisStyle.richText = true;
|
|
axisStyle.fontSize = 11;
|
|
Handles.Label(midPoint - (Vector3.up * 0.3f), axisText, axisStyle);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void DrawOverlay(SceneView view)
|
|
{
|
|
Handles.BeginGUI();
|
|
|
|
// Positioning the overlay in the bottom right
|
|
float width = 140;
|
|
float height = 90;
|
|
Rect rect = new Rect(view.position.width - width - 10, view.position.height - height - 30, width, height);
|
|
|
|
GUILayout.BeginArea(rect, "MEASURE TOOL", GUI.skin.window);
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
IsEnabled = GUILayout.Toggle(IsEnabled, " Enable Tool");
|
|
ShowTotalDistance = GUILayout.Toggle(ShowTotalDistance, " Show Total");
|
|
ShowAxisBreakdown = GUILayout.Toggle(ShowAxisBreakdown, " Axis Breakdown");
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
EditorPrefs.SetBool("MeasureTool_Enabled", IsEnabled);
|
|
EditorPrefs.SetBool("MeasureTool_Axis", ShowAxisBreakdown);
|
|
SceneView.RepaintAll();
|
|
}
|
|
|
|
GUILayout.EndArea();
|
|
Handles.EndGUI();
|
|
}
|
|
|
|
private static GUIStyle GetLabelStyle(Color textColor, Color bgColor)
|
|
{
|
|
GUIStyle style = new GUIStyle();
|
|
style.normal.textColor = textColor;
|
|
style.fontSize = 13;
|
|
style.fontStyle = FontStyle.Bold;
|
|
style.alignment = TextAnchor.MiddleCenter;
|
|
style.padding = new RectOffset(4, 4, 2, 2);
|
|
|
|
// Create a background texture dynamically
|
|
Texture2D tex = new Texture2D(1, 1);
|
|
tex.SetPixel(0, 0, bgColor);
|
|
tex.Apply();
|
|
style.normal.background = tex;
|
|
|
|
return style;
|
|
}
|
|
}
|
|
} |