I just made a simple Editor overriding EditorTool.
If enabled, when user holds the left shift button, the editor draws a line and shows the size:
[EditorTool("Ruler Tool")]
public class RulerTool : EditorTool
{
VisualElement _toolRootElement;
bool _downEvent;
bool _upEvent;
private Vector3 _startPosition;
public override void OnActivated()
{
_toolRootElement = new VisualElement();
_toolRootElement.style.width = 200;
var backgroundColor = EditorGUIUtility.isProSkin ? new Color(0.21f, 0.21f, 0.21f, 0.8f) : new Color(0.8f, 0.8f, 0.8f, 0.8f);
_toolRootElement.style.backgroundColor = backgroundColor;
_toolRootElement.style.marginLeft = 10f;
_toolRootElement.style.marginBottom = 10f;
_toolRootElement.style.paddingTop = 5f;
_toolRootElement.style.paddingRight = 5f;
_toolRootElement.style.paddingLeft = 5f;
_toolRootElement.style.paddingBottom = 5f;
var titleLabel = new Label("Ruler Tool");
titleLabel.style.unityTextAlign = TextAnchor.UpperCenter;
_toolRootElement.Add(titleLabel);
var sv = SceneView.lastActiveSceneView;
sv.rootVisualElement.Add(_toolRootElement);
sv.rootVisualElement.style.flexDirection = FlexDirection.ColumnReverse;
SceneView.beforeSceneGui += BeforeSceneGUI;
}
public override void OnWillBeDeactivated()
{
_toolRootElement?.RemoveFromHierarchy();
SceneView.beforeSceneGui -= BeforeSceneGUI;
}
void BeforeSceneGUI(SceneView sceneView)
{
if (!ToolManager.IsActiveTool(this))
return;
if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.LeftShift)
{
if (!_downEvent)
_startPosition = GetCurrentMousePositionInScene();
_downEvent = true;
Event.current.Use();
}
else if (Event.current.type == EventType.KeyUp && Event.current.keyCode == KeyCode.LeftShift)
{
_downEvent = false;
Event.current.Use();
}
}
public override void OnToolGUI(EditorWindow window)
{
if (!(window is SceneView))
return;
if (!ToolManager.IsActiveTool(this))
return;
if (_downEvent)
{
float distance = Vector3.Distance(_startPosition, GetCurrentMousePositionInScene());
Handles.Label(GetCurrentMousePositionInScene() + new Vector3(0, 0, 0.7f), distance.ToString());
Handles.DrawLine(_startPosition, GetCurrentMousePositionInScene());
Handles.DrawWireDisc(GetCurrentMousePositionInScene(), Vector3.up, 0.5f);
}
window.Repaint();
}
Vector3 GetCurrentMousePositionInScene()
{
Vector3 mousePosition = Event.current.mousePosition;
var placeObject = HandleUtility.PlaceObject(mousePosition, out var newPosition, out var normal);
return placeObject ? newPosition : HandleUtility.GUIPointToWorldRay(mousePosition).GetPoint(10);
}
}