Files
BABA_YAGA/Assets/Editor/MeasureTool.cs
2026-03-26 20:27:19 +07:00

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;
}
}
}