备份CatanBuilding瘦身独立工程
This commit is contained in:
236
Assets/Scripts/UI/ScratchTicket/EditablePolygon.cs
Normal file
236
Assets/Scripts/UI/ScratchTicket/EditablePolygon.cs
Normal file
@@ -0,0 +1,236 @@
|
||||
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<PolygonCollider2D>();
|
||||
if (image == null) image = GetComponent<Image>();
|
||||
|
||||
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<RaycastResult> results = new List<RaycastResult>();
|
||||
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<RectTransform>();
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user