diff options
Diffstat (limited to 'SurvivalTest/Assets/Tools/EditorGUIHelper/Editor/EditorHandlesHelper.cs')
-rw-r--r-- | SurvivalTest/Assets/Tools/EditorGUIHelper/Editor/EditorHandlesHelper.cs | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/SurvivalTest/Assets/Tools/EditorGUIHelper/Editor/EditorHandlesHelper.cs b/SurvivalTest/Assets/Tools/EditorGUIHelper/Editor/EditorHandlesHelper.cs new file mode 100644 index 0000000..6a07ab4 --- /dev/null +++ b/SurvivalTest/Assets/Tools/EditorGUIHelper/Editor/EditorHandlesHelper.cs @@ -0,0 +1,279 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +// https://docs.unity3d.com/ScriptReference/Handles.html + +// Scene视图中的自定义handles +public static class EditorHandlesHelper +{ + + static int s_ValueScaleHandleHash; + static int s_PositionArrowHandleHash; + + // limit value 数据 + static float s_StartScale; + static float s_ValueDrag; + static float s_ScaleDrawLength; + + static Vector3 s_LastPosition; + + // style + static GUIStyle s_StyleBlackLabel; + static GUIStyle s_StyleWhiteLabel; + static Dictionary<int/*color*/, GUIStyle> s_StyleLabels; + + static EditorHandlesHelper() + { + s_ValueScaleHandleHash = "ValueScaleHandle".GetHashCode(); + s_PositionArrowHandleHash = "PositionArrowHandle".GetHashCode(); + + + SetupStyles(); + } + + static void SetupStyles() + { + s_StyleBlackLabel = new GUIStyle(); + s_StyleBlackLabel.normal.textColor = Color.black; + s_StyleWhiteLabel = new GUIStyle(); + s_StyleWhiteLabel.normal.textColor = Color.white; + s_StyleLabels = new Dictionary<int, GUIStyle>(); + } + + #region 单一handle + + /// <summary> + /// 无事件箭头 + /// </summary> + /// <param name="position"></param> + /// <param name="direction"></param> + /// <param name="length"></param> + /// <param name="arrowSize"></param> + /// <param name="dotted"></param> + public static void Arrow(Vector3 position, Vector3 direction, float length = 1f, float arrowSize = 0.1f, bool dotted = false) + { + direction = direction.normalized; + if(!dotted) + Handles.DrawLine(position, position + direction * length); + else + Handles.DrawDottedLine(position, position + direction * length,1f); + Handles.ConeHandleCap(0, position + direction * length, Quaternion.LookRotation(direction, Vector3.up), arrowSize, EventType.Repaint); + } + + /// <summary> + /// 处理位置的可拖拽箭头 + /// </summary> + /// <param name="currentValue"></param> + /// <param name="position"></param> + /// <param name="direction"></param> + /// <param name="length"></param> + /// <param name="arrowSize"></param> + /// <param name="dotted"></param> + /// <returns></returns> + public static Vector3 PositionArrow(Vector3 position, Vector3 direction, float length, float arrowSize, bool dotted = false) + { + direction = direction.normalized; + + Vector3 value = Vector3.zero; + Handles.CapFunction capFunc = Handles.ConeHandleCap; + + Quaternion capRot = Quaternion.LookRotation(direction, Vector3.up); + float size = arrowSize; + Vector3 arrowPos = position + direction * length; + + int id = GUIUtility.GetControlID(s_PositionArrowHandleHash, FocusType.Keyboard); + + Event current = Event.current; + switch (current.GetTypeForControl(id)) + { + case EventType.MouseDown: + if ((HandleUtility.nearestControl == id && current.button == 0) || (GUIUtility.keyboardControl == id && current.button == 2)) + { + s_LastPosition = Camera.current.ScreenToWorldPoint(Event.current.mousePosition); + + GUIUtility.keyboardControl = id; + GUIUtility.hotControl = id; + current.Use(); + EditorGUIUtility.SetWantsMouseJumping(1); + } + break; + case EventType.MouseUp: + if (GUIUtility.hotControl == id && (current.button == 0 || current.button == 2)) + { + GUIUtility.keyboardControl = 0; + GUIUtility.hotControl = 0; + current.Use(); + EditorGUIUtility.SetWantsMouseJumping(0); + } + break; + case EventType.MouseDrag: + if (GUIUtility.hotControl == id) + { + Vector3 worldpos = Camera.current.ScreenToWorldPoint(Event.current.mousePosition); + value = worldpos - s_LastPosition; + + s_LastPosition = worldpos; + + GUI.changed = true; + current.Use(); + } + break; + //case EventType.KeyDown: + // if (GUIUtility.hotControl == id && current.keyCode == KeyCode.Escape) + // { + // GUIUtility.hotControl = 0; + // GUI.changed = true; + // current.Use(); + // } + // break; + case EventType.Repaint: + { + Color color = Color.white; + if (id == GUIUtility.keyboardControl) + { + color = Handles.color; + Handles.color = Handles.selectedColor; + } + capFunc(id, arrowPos, capRot, size * 0.15f, EventType.Repaint); + DottedLine(position, arrowPos, 1f, dotted); + if (id == GUIUtility.keyboardControl) + { + Handles.color = color; + } + break; + } + case EventType.Layout: + HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(arrowPos, size * 0.15f)); + break; + } + + return value; + } + + public static void DottedLine(Vector3 p1, Vector3 p2, float length, bool dotted = true) + { + if (!dotted) + Handles.DrawLine(p1, p2); + else + Handles.DrawDottedLine(p1, p2, 1f); + } + + // 控制数值的箭头 + public static float ScaleValue(float value, Vector3 position, Vector3 direction, float length, Handles.CapFunction capFunc, Quaternion capRot, float size, float snap = 0) + { + Handles.DrawLine(position, position + direction * length); + value = ScaleValue(value, position + direction, capRot, size, capFunc, snap); + return value; + } + + // 控制数值的handle + public static float ScaleValue(float value, Vector3 position, Quaternion rotation, float size, Handles.CapFunction capFunc, float snap) + { + int controlID = GUIUtility.GetControlID(s_ValueScaleHandleHash, FocusType.Keyboard); + int id = controlID; + Event current = Event.current; + switch (current.GetTypeForControl(id)) + { + case EventType.MouseDown: + if ((HandleUtility.nearestControl == id && current.button == 0) || (GUIUtility.keyboardControl == id && current.button == 2)) + { + GUIUtility.keyboardControl = id; + GUIUtility.hotControl = id; + s_StartScale = value; + s_ValueDrag = 0f; + current.Use(); + EditorGUIUtility.SetWantsMouseJumping(1); + } + break; + case EventType.MouseUp: + if (GUIUtility.hotControl == id && (current.button == 0 || current.button == 2)) + { + GUIUtility.hotControl = 0; + s_ScaleDrawLength = 1f; + current.Use(); + EditorGUIUtility.SetWantsMouseJumping(0); + } + break; + case EventType.MouseDrag: + if (GUIUtility.hotControl == id) + { + s_ValueDrag += HandleUtility.niceMouseDelta * 0.01f; + //value = (Handles.SnapValue(s_ValueDrag, snap) + 1f) * s_StartScale; + value = Camera.current.ScreenToWorldPoint(Event.current.mousePosition).x - 1; + s_ScaleDrawLength = value / s_StartScale; + GUI.changed = true; + current.Use(); + } + break; + case EventType.KeyDown: + if (GUIUtility.hotControl == id && current.keyCode == KeyCode.Escape) + { + value = s_StartScale; + s_ScaleDrawLength = 1f; + GUIUtility.hotControl = 0; + GUI.changed = true; + current.Use(); + } + break; + case EventType.Repaint: + { + Color color = Color.white; + if (id == GUIUtility.keyboardControl) + { + color = Handles.color; + Handles.color = Handles.selectedColor; + } + capFunc(id, position, rotation, size * 0.15f, EventType.Repaint); + if (id == GUIUtility.keyboardControl) + { + Handles.color = color; + } + break; + } + case EventType.Layout: + HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(position, size * 0.15f)); + break; + } + return value; + } + + // 带背景的label + public static void Label(Vector3 position, string label, Color textColor) + { + GUIStyle textStyle = TryGetLabelStyleOrCreate(textColor); + Handles.Label(position, label, textStyle); + } + + public static void WireCube(Vector3 position, Vector3 size, Color col) + { + Color c = Handles.color; + Handles.color = col; + Handles.DrawWireCube(position, size); + Handles.color = c; + } + + #endregion + + #region 复合handle + + #endregion + + #region 内部方法 + + static GUIStyle TryGetLabelStyleOrCreate(Color color) + { + GUIStyle style; + if (!s_StyleLabels.TryGetValue(color.GetHashCode(), out style)) + { + style = new GUIStyle(); + style.normal.textColor = color; + s_StyleLabels.Add(color.GetHashCode(), style); + } + return style; + } + + #endregion + +} |