Created
October 14, 2023 03:10
-
-
Save YN-Studio/e8592708130681db053a3f74659443f1 to your computer and use it in GitHub Desktop.
基于Odin Inspector的Unity2D测量工具。Unity2D measure tool using Odin Inspector
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 System.Collections.Generic; | |
using Sirenix.OdinInspector; | |
using Sirenix.OdinInspector.Editor; | |
using UnityEditor; | |
using UnityEngine; | |
/// <summary> | |
/// 地编中使用的测量工具(2D) | |
/// </summary> | |
public class MeasureToolEditor : OdinEditorWindow | |
{ | |
#if UNITY_EDITOR | |
private bool startMeasure; | |
[BoxGroup("测量状态")] | |
[HideIf("@startMeasure")] | |
[PropertyOrder(-1)] | |
[Button("开始测量", ButtonSizes.Large), GUIColor(0, 1, 0)] | |
public void StartMeasure() | |
{ | |
startMeasure = true; | |
} | |
[BoxGroup("测量状态")] | |
[HideIf("@!startMeasure")] | |
[PropertyOrder(-1)] | |
[Button("停止测量", ButtonSizes.Large), GUIColor(1, 0, 0)] | |
public void StopMeasure() | |
{ | |
startMeasure = false; | |
measuring = false; | |
} | |
[BoxGroup("测量状态")] | |
[LabelWidth(150)] | |
public bool snap = true; | |
[BoxGroup("测量状态")] | |
[ShowIf("@snap")] | |
[LabelWidth(150)] | |
public float snapDistance = 0.25f; | |
[BoxGroup("显示具体的数值")] | |
[LabelText("显示坐标")] | |
[LabelWidth(150)] | |
public bool showCoordinate; | |
[BoxGroup("显示具体的数值")] | |
[LabelText("显示距离")] | |
[LabelWidth(150)] | |
public bool showDis; | |
//[BoxGroup("显示具体的数值")] | |
[Button("增加新list", ButtonSizes.Large), GUIColor(0.3f, 0.8f, 0.8f)] | |
[ButtonGroup("显示具体的数值/")] | |
public void AddListButton() | |
{ | |
AddNewList(); | |
} | |
[Button("清除所有List", ButtonSizes.Large), GUIColor(1, 0, 0)] | |
[ButtonGroup("显示具体的数值/")] | |
public void CleanAllList() | |
{ | |
measurePointList.Clear(); | |
closestList = 0; | |
} | |
[BoxGroup("UI参数")] | |
[LabelWidth(150)] | |
public float unfocusLineWidth = 1f; | |
[BoxGroup("UI参数")] | |
[LabelWidth(150)] | |
public float focusLineWidth = 2f; | |
[BoxGroup("UI参数")] | |
[LabelWidth(150)] | |
public int fontSize = 15; | |
private Color[] colorArray; | |
private bool measuring; | |
private Vector3 pos; | |
private int closestList; | |
private int currentAddList; | |
public List<List<Vector3>> measurePointList; | |
private Vector3 closestPoint; | |
private float rightClickTimer; | |
[Tooltip("Scene View摄像机的Z轴坐标")] | |
private float distanceToSceneCamera; | |
#region 系统 | |
[MenuItem("工具/测量工具 %m")] | |
private static void OpenWindow() | |
{ | |
GetWindow<MeasureToolEditor>("测量工具").Show(); | |
} | |
protected override void OnEnable() | |
{ | |
SceneView.duringSceneGui -= OnSceneGUI; | |
SceneView.duringSceneGui += OnSceneGUI; | |
if (measurePointList == null) | |
{ | |
measurePointList = new List<List<Vector3>>(); | |
measurePointList.Add(new List<Vector3>()); | |
} | |
foreach (var colorPalette in ColorPaletteManager.Instance.ColorPalettes) | |
{ | |
if (colorPalette.Name == "Measure Tool") | |
{ | |
colorArray = colorPalette.Colors.ToArray(); | |
} | |
} | |
closestList = 0; | |
} | |
protected override void OnDestroy() | |
{ | |
SceneView.duringSceneGui -= OnSceneGUI; | |
measuring = false; | |
} | |
private void OnSceneGUI(SceneView sceneView) | |
{ | |
if (sceneAssetData != null) | |
{ | |
if (sceneAssetData.measurePointsList != null) | |
{ | |
measurePointList = sceneAssetData.measurePointsList; | |
} | |
} | |
if(startMeasure) | |
{ | |
Event currentEvent = Event.current; | |
pos = HandleUtility.GUIPointToWorldRay(currentEvent.mousePosition).origin; | |
pos.z = 0; | |
distanceToSceneCamera = SceneView.currentDrawingSceneView.camera.transform.position.z; | |
if (snap) | |
{ | |
pos.x = snapDistance * Mathf.Round(pos.x / snapDistance); | |
pos.y = snapDistance * Mathf.Round(pos.y / snapDistance); | |
} | |
DebugExtension.DebugCircle(pos, Vector3.forward, Color.green, 0.1f); | |
GetClosestPoint(out closestPoint, out closestList); | |
measuring = true; | |
} | |
if (measuring) | |
{ | |
AddMeasurePoint(); | |
RemovePoint(); | |
} | |
if (measurePointList != null && measurePointList.Count > 0 && measurePointList[closestList] != null) | |
{ | |
for (int i = 0; i < measurePointList.Count; i++) | |
{ | |
DrawMeasurePoint(measurePointList[i], colorArray[i < colorArray.Length ? i : 0]); | |
DrawLineBetweenPoints(measurePointList[i], colorArray[i < colorArray.Length ? i : 0], (closestList == i && startMeasure) ? focusLineWidth : unfocusLineWidth); | |
} | |
} | |
} | |
private void AddMeasurePoint() | |
{ | |
if (Event.current.type == EventType.MouseDown && Event.current.button == 0) | |
{ | |
if (measurePointList.Count == 0) | |
{ | |
measurePointList.Add(new List<Vector3>()); | |
currentAddList = 0; | |
} | |
measurePointList[currentAddList].Add(pos); | |
Repaint(); | |
} | |
} | |
/// <summary> | |
/// 鼠标右键(去除点) | |
/// </summary> | |
private void RemovePoint() | |
{ | |
if (Event.current.type == EventType.MouseDown && Event.current.button == 1) | |
{ | |
//用一个Timer来避免与长按鼠标右键的操作(拖动SceneView)重合 | |
rightClickTimer = (float)EditorApplication.timeSinceStartup; | |
} | |
if (Event.current.type == EventType.MouseUp && Event.current.button == 1) | |
{ | |
float timeDiff = (float)EditorApplication.timeSinceStartup - rightClickTimer; | |
//如果按下按键的时间小于0.4秒,则去除 | |
if (timeDiff < 0.4f) | |
{ | |
if (measurePointList.Count > 0 && measurePointList[closestList] != null) | |
{ | |
RemoveClosestPoint(); | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// 增加新的测量路径 | |
/// </summary> | |
private void AddNewList() | |
{ | |
measurePointList.Add(new List<Vector3>()); | |
currentAddList = measurePointList.Count - 1; | |
} | |
#endregion | |
private void GetClosestPoint(out Vector3 closestPoint, out int closestPointList) | |
{ | |
Event currentEvent = Event.current; | |
var tempPos = HandleUtility.GUIPointToWorldRay(currentEvent.mousePosition).origin; | |
var closestDistance = Mathf.Infinity; | |
closestPoint = new Vector3(); | |
closestPointList = 0; | |
//找到离鼠标最近的点 | |
for (var index = 0; index < measurePointList.Count; index++) | |
{ | |
var pointList = measurePointList[index]; | |
for (var i = 0; i < pointList.Count; i++) | |
{ | |
var point = pointList[i]; | |
Vector3 direction = point - tempPos; | |
float distanceSqr = direction.sqrMagnitude; | |
if (distanceSqr < closestDistance) | |
{ | |
closestDistance = distanceSqr; | |
closestPoint = point; | |
closestPointList = index; | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// 移除离鼠标位置最近的点 | |
/// </summary> | |
private void RemoveClosestPoint() | |
{ | |
measurePointList[closestList].Remove(closestPoint); | |
} | |
/// <summary> | |
/// 绘制点和坐标 | |
/// </summary> | |
private void DrawMeasurePoint(List<Vector3> listToDraw, Color distanceColor) | |
{ | |
if (listToDraw.Count > 0) | |
{ | |
foreach (var point in listToDraw) | |
{ | |
DebugExtension.DebugPoint(point, distanceColor, 0.5f); | |
if (showCoordinate) | |
{ | |
//根据sceneCamera的位置,调整字的位置 | |
/*float dist = Vector3.Distance(UnityEngine.Camera.main.transform.position, point); | |
var newScale = dist / 10 * 3;*/ | |
DrawCoordinate(point + new Vector3(0, 0.4f, 0), point, distanceColor); | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// 绘制点与点之间的距离 | |
/// </summary> | |
private void DrawLineBetweenPoints(List<Vector3> listToDraw, Color color, float lineWidth) | |
{ | |
if (listToDraw.Count >= 2) | |
{ | |
for (int i = 0; i < listToDraw.Count - 1; i++) | |
{ | |
var arrowDirection = (listToDraw[i + 1] - listToDraw[i]).normalized; | |
var pointDis = Vector3.Distance(listToDraw[i], listToDraw[i + 1]); | |
Vector3 midPoint = new Vector3((listToDraw[i].x + listToDraw[i + 1].x) / 2, | |
(listToDraw[i].y + listToDraw[i + 1].y) / 2); | |
var xDis = Mathf.Abs(listToDraw[i].x - listToDraw[i + 1].x); | |
var yDis = Mathf.Abs(listToDraw[i].y - listToDraw[i + 1].y); | |
if (showDis) | |
{ | |
DrawDistance(midPoint + new Vector3(0, 1.5f, 0), xDis, yDis, color); | |
} | |
Handles.color = color; | |
Handles.DrawLine(listToDraw[i], listToDraw[i + 1], lineWidth); | |
} | |
} | |
} | |
GUIStyle style = new GUIStyle(); | |
private void DrawDistance(Vector3 textPosition, float xDis, float yDis, Color textColor) | |
{ | |
style.fontSize = fontSize; | |
style.normal.textColor = textColor; | |
Handles.Label(textPosition, "X: " + xDis + "\nY: " + yDis, style); | |
} | |
private void DrawCoordinate(Vector3 textPosition, Vector3 pos, Color textColor) | |
{ | |
style.fontSize = fontSize; | |
style.normal.textColor = textColor; | |
Handles.Label(textPosition, "Position: " + pos, style); | |
} | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment