using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;
//============================================================
//支持中文,文件使用UTF-8编码
//@author JiphuTzu
//@create 20220910
//@company Umawerse
//
//@description:
//============================================================
namespace Umawerse.FiniteStateMachines
{
public class PolygonDrawState : DrawingState
{
private Mesh _mesh;
private LineRenderer _line;
public PolygonDrawState(ToolsBootstrap root) : base(root, StateName.polygon, 3, 99)
{
}
protected override void OnTap(Vector3 pos)
{
AddPoint(pos);
}
protected override void OnDoubleTap(Vector3 pos)
{
AddPoint(pos);
}
protected override void UpdatePreview(Vector3 pos)
{
var verts = new List<Vector3>();
verts.AddRange(vertices);
verts.Add(pos);
Show(verts);
}
public override void Init()
{
base.Init();
_mesh = new Mesh();
target.AddComponent<MeshFilter>().mesh = _mesh;
var renderer = target.AddComponent<MeshRenderer>();
renderer.material = root.ployMaterial;
renderer.material.color = Color.green;
//
var mr = new GameObject("LineRender");
mr.transform.SetParent(target.transform);
_line = mr.AddComponent<LineRenderer>();
_line.sortingOrder = -1;
_line.startWidth = 0.3f;
_line.endWidth = 0.3f;
_line.numCornerVertices = 3;
_line.material = root.solidLineMaterial;
_line.material.color = Color.green;
}
public override void Complete()
{
Show(vertices);
var mc = target.AddComponent<MeshCollider>();
//var label = Object.Instantiate(root.labelPrefab, target.transform);
//label.Init($"面积:", false);
//label.SetPosition(mc.bounds.center + Vector3.up);
//label.SetAlignment();
}
public override void AddPoint(Vector3 position, bool showImmediately = true)
{
vertices.Add(position);
if (showImmediately)
{
var h = vertices[0].y > position.y ? vertices[0].y : position.y;
for (var i = 0; i < vertices.Count; i++)
{
var v = vertices[i];
v.y = h;
vertices[i] = v;
if (i + 1 < target.transform.childCount)
target.transform.GetChild(i + 1).position = v;
}
}
var ployPoint = Object.Instantiate(root.ployPointPrefab, target.transform);
ployPoint.transform.localPosition = vertices[vertices.Count - 1];
var mr = ployPoint.GetComponent<MeshRenderer>();
mr.material.SetColor(COLOR_ID, Color.green);
mr.sortingOrder = 2;
if (vertices.Count < 3 || !showImmediately) return;
Show(vertices);
}
private void Show(List<Vector3> verts)
{
var triangles = new List<int>();
for (var i = 2; i < verts.Count; i++)
{
triangles.Add(0);
if (IsUp(verts[i] - verts[0], verts[i - 1] - verts[0]))
{
triangles.Add(i);
triangles.Add(i - 1);
}
else
{
triangles.Add(i - 1);
triangles.Add(i);
}
}
_mesh.vertices = verts.ToArray();
_mesh.triangles = triangles.ToArray();
//
var vs = new Vector3[verts.Count + 1];
verts.CopyTo(vs);
vs[vs.Length - 1] = vs[0];
_line.positionCount = vs.Length;
_line.SetPositions(vs);
_line.material.SetFloat("_Cnt", GetLength(vs) / 3);
}
private bool IsUp(Vector3 a, Vector3 b)
{
var nor = Vector3.Cross(a, b);
var angle = Vector3.Dot(nor, Vector3.up);
return angle > 0;
}
private float GetLength(Vector3[] verts)
{
var length = 0f;
for (var i = 1; i < verts.Length; i++)
{
length += Vector3.Distance(verts[i], verts[i - 1]);
}
return length;
}
}
}