Commit 1
This commit is contained in:
149
Assets/Editor/MeasureTool.cs
Normal file
149
Assets/Editor/MeasureTool.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
// ===============================================================================
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user