using GameCore; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace game { [RequireComponent(typeof(PolygonCollider2D))] [RequireComponent(typeof(Image))] public class EditablePolygon : MonoBehaviour { public Color polygonColor = new Color(0.5f, 0.5f, 1f, 0.5f); public Vector2[] points = new Vector2[] { new Vector2(0, 0), new Vector2(100, 50), new Vector2(50, 100), new Vector2(-50, 50) }; private PolygonCollider2D polygonCollider; private Image image; void OnValidate() { UpdatePolygon(); } void Awake() { UpdatePolygon(); } public void UpdatePolygon() { if (polygonCollider == null) polygonCollider = GetComponent(); if (image == null) image = GetComponent(); polygonCollider.points = points; image.color = polygonColor; } public bool IsDown() { if (EventSystem.current == null) { return true; } PointerEventData pointerEventData = new PointerEventData(EventSystem.current) { position = Input.mousePosition }; List results = new List(); EventSystem.current.RaycastAll(pointerEventData, results); if (results.Count > 0 && results[0].gameObject == gameObject) { return true; } return false; } public bool ContainsPoint(Vector2 position) { if (!IsDown()) { return false; } RectTransformUtility.ScreenPointToLocalPointInRectangle( transform as RectTransform, position, UIManager.Instance.UICanvas.worldCamera, out Vector2 localPoint); //bool flag = polygonCollider.OverlapPoint(localPoint); //if (IsPointInPolygon(localPoint, polygonCollider.points)) //{ // Debug.LogError("点在多边形内"); //} //else //{ // Debug.LogError("点不在多边形内"); //} return IsPointInPolygon(localPoint, points); } bool IsPointInPolygon(Vector2 point, Vector2[] polygon) { int polygonLength = polygon.Length; bool inside = false; // 从点向右发射水平射线 for (int i = 0, j = polygonLength - 1; i < polygonLength; j = i++) { Vector2 pi = polygon[i]; Vector2 pj = polygon[j]; // 检查点是否在顶点上 if (Mathf.Approximately(point.x, pi.x) && Mathf.Approximately(point.y, pi.y)) return true; // 检查边是否与射线相交 if (((pi.y > point.y) != (pj.y > point.y)) && (point.x < (pj.x - pi.x) * (point.y - pi.y) / (pj.y - pi.y) + pi.x)) { inside = !inside; } } return inside; } } } #if UNITY_EDITOR namespace game { using UnityEditor; [CustomEditor(typeof(EditablePolygon))] public class EditablePolygonEditor : Editor { private EditablePolygon polygon; private SerializedProperty pointsProperty; private SerializedProperty colorProperty; private const float handleSize = 10f; private int selectedIndex = -1; void OnEnable() { polygon = (EditablePolygon)target; pointsProperty = serializedObject.FindProperty("points"); colorProperty = serializedObject.FindProperty("polygonColor"); } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(colorProperty); EditorGUILayout.LabelField("多边形顶点", EditorStyles.boldLabel); for (int i = 0; i < pointsProperty.arraySize; i++) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(pointsProperty.GetArrayElementAtIndex(i), new GUIContent("顶点 " + i)); if (GUILayout.Button("删除", GUILayout.Width(50))) { pointsProperty.DeleteArrayElementAtIndex(i); serializedObject.ApplyModifiedProperties(); polygon.UpdatePolygon(); return; } EditorGUILayout.EndHorizontal(); } if (GUILayout.Button("添加顶点")) { pointsProperty.arraySize++; serializedObject.ApplyModifiedProperties(); polygon.UpdatePolygon(); } serializedObject.ApplyModifiedProperties(); } void OnSceneGUI() { RectTransform rectTransform = polygon.GetComponent(); for (int i = 0; i < polygon.points.Length; i++) { Vector2 point = polygon.points[i]; Vector3 worldPoint = rectTransform.TransformPoint(point); Handles.color = i == selectedIndex ? Color.red : Color.green; // 绘制可拖拽的handle EditorGUI.BeginChangeCheck(); var fmh_147_21_638823244657839550 = Quaternion.identity; Vector3 newWorldPoint = Handles.FreeMoveHandle( worldPoint, handleSize, Vector3.zero, Handles.CircleHandleCap); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(polygon, "Move Polygon Point"); polygon.points[i] = rectTransform.InverseTransformPoint(newWorldPoint); polygon.UpdatePolygon(); } // 检查点击选择 if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && Vector2.Distance(HandleUtility.WorldToGUIPoint(worldPoint), Event.current.mousePosition) < handleSize) { selectedIndex = i; Event.current.Use(); } } // 绘制多边形线框 Handles.color = polygon.polygonColor; Vector3[] worldPoints = new Vector3[polygon.points.Length + 1]; for (int i = 0; i < polygon.points.Length; i++) { worldPoints[i] = rectTransform.TransformPoint(polygon.points[i]); } worldPoints[worldPoints.Length - 1] = worldPoints[0]; Handles.DrawPolyLine(worldPoints); // 删除选中的顶点 if (selectedIndex != -1 && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Delete) { Undo.RecordObject(polygon, "Delete Polygon Point"); var newPoints = new Vector2[polygon.points.Length - 1]; for (int i = 0, j = 0; i < polygon.points.Length; i++) { if (i != selectedIndex) newPoints[j++] = polygon.points[i]; } polygon.points = newPoints; selectedIndex = -1; polygon.UpdatePolygon(); Event.current.Use(); } } } } #endif