389 lines
13 KiB
C#
389 lines
13 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
namespace XUGL
|
||
{
|
||
public static class UGLHelper
|
||
{
|
||
public static bool IsValueEqualsColor(Color32 color1, Color32 color2)
|
||
{
|
||
return color1.a == color2.a &&
|
||
color1.b == color2.b &&
|
||
color1.g == color2.g &&
|
||
color1.r == color2.r;
|
||
}
|
||
|
||
public static bool IsValueEqualsColor(Color color1, Color color2)
|
||
{
|
||
return color1.a == color2.a &&
|
||
color1.b == color2.b &&
|
||
color1.g == color2.g &&
|
||
color1.r == color2.r;
|
||
}
|
||
|
||
public static bool IsValueEqualsString(string str1, string str2)
|
||
{
|
||
if (str1 == null && str2 == null)
|
||
return true;
|
||
else if (str1 != null && str2 != null)
|
||
return str1.Equals(str2);
|
||
else return false;
|
||
}
|
||
|
||
public static bool IsValueEqualsVector2(Vector2 v1, Vector2 v2)
|
||
{
|
||
return v1.x == v2.x &&
|
||
v1.y == v2.y;
|
||
}
|
||
|
||
public static bool IsValueEqualsVector3(Vector3 v1, Vector3 v2)
|
||
{
|
||
return v1.x == v2.x &&
|
||
v1.y == v2.y &&
|
||
v1.z == v2.z;
|
||
}
|
||
|
||
public static bool IsValueEqualsVector3(Vector3 v1, Vector2 v2)
|
||
{
|
||
return v1.x == v2.x &&
|
||
v1.y == v2.y;
|
||
}
|
||
|
||
public static bool IsValueEqualsList<T>(List<T> list1, List<T> list2)
|
||
{
|
||
if (list1 == null || list2 == null)
|
||
return false;
|
||
|
||
if (list1.Count != list2.Count)
|
||
return false;
|
||
|
||
for (int i = 0; i < list1.Count; i++)
|
||
{
|
||
if (list1[i] == null && list2[i] == null)
|
||
{ }
|
||
else
|
||
{
|
||
if (list1[i] != null)
|
||
{
|
||
if (!list1[i].Equals(list2[i]))
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
if (!list2[i].Equals(list1[i]))
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
public static bool IsClearColor(Color32 color)
|
||
{
|
||
return color.a == 0 &&
|
||
color.b == 0 &&
|
||
color.g == 0 &&
|
||
color.r == 0;
|
||
}
|
||
|
||
public static bool IsClearColor(Color color)
|
||
{
|
||
return color.a == 0 &&
|
||
color.b == 0 &&
|
||
color.g == 0 &&
|
||
color.r == 0;
|
||
}
|
||
|
||
public static bool IsZeroVector(Vector3 pos)
|
||
{
|
||
return pos.x == 0 &&
|
||
pos.y == 0 &&
|
||
pos.z == 0;
|
||
}
|
||
|
||
public static Vector3 RotateRound(Vector3 position, Vector3 center, Vector3 axis, float angle)
|
||
{
|
||
Vector3 point = Quaternion.AngleAxis(angle, axis) * (position - center);
|
||
Vector3 resultVec3 = center + point;
|
||
return resultVec3;
|
||
}
|
||
|
||
public static void GetBezierList(ref List<Vector3> posList, Vector3 sp, Vector3 ep,
|
||
Vector3 lsp, Vector3 nep, float smoothness = 2f, float k = 2.0f)
|
||
{
|
||
float dist = Mathf.Abs(sp.x - ep.x);
|
||
Vector3 cp1, cp2;
|
||
var dir = (ep - sp).normalized;
|
||
var diff = dist / k;
|
||
if (lsp == sp)
|
||
{
|
||
cp1 = sp + dist / k * dir * 1;
|
||
cp1.y = sp.y;
|
||
cp1 = sp;
|
||
}
|
||
else
|
||
{
|
||
cp1 = sp + (ep - lsp).normalized * diff;
|
||
}
|
||
if (nep == ep) cp2 = ep;
|
||
else cp2 = ep - (nep - sp).normalized * diff;
|
||
dist = Vector3.Distance(sp, ep);
|
||
int segment = (int) (dist / (smoothness <= 0 ? 2f : smoothness));
|
||
if (segment < 1) segment = (int) (dist / 0.5f);
|
||
if (segment < 4) segment = 4;
|
||
GetBezierList2(ref posList, sp, ep, segment, cp1, cp2);
|
||
if (posList.Count < 2)
|
||
{
|
||
posList.Clear();
|
||
posList.Add(sp);
|
||
posList.Add(ep);
|
||
}
|
||
}
|
||
|
||
public static void GetBezierListVertical(ref List<Vector3> posList, Vector3 sp, Vector3 ep,
|
||
float smoothness = 2f, float k = 2.0f)
|
||
{
|
||
Vector3 dir = (ep - sp).normalized;
|
||
float dist = Vector3.Distance(sp, ep);
|
||
Vector3 cp1 = sp + dist / k * dir * 1;
|
||
Vector3 cp2 = sp + dist / k * dir * (k - 1);
|
||
cp1.x = sp.x;
|
||
cp2.x = ep.x;
|
||
int segment = (int) (dist / (smoothness <= 0 ? 2f : smoothness));
|
||
GetBezierList2(ref posList, sp, ep, segment, cp1, cp2);
|
||
if (posList.Count < 2)
|
||
{
|
||
posList.Clear();
|
||
posList.Add(sp);
|
||
posList.Add(ep);
|
||
}
|
||
}
|
||
|
||
public static List<Vector3> GetBezierList(Vector3 sp, Vector3 ep, int segment, Vector3 cp)
|
||
{
|
||
List<Vector3> list = new List<Vector3>();
|
||
for (int i = 0; i < segment; i++)
|
||
{
|
||
list.Add(GetBezier(i / (float) segment, sp, cp, ep));
|
||
}
|
||
list.Add(ep);
|
||
return list;
|
||
}
|
||
|
||
public static void GetBezierList2(ref List<Vector3> posList, Vector3 sp, Vector3 ep,
|
||
int segment, Vector3 cp, Vector3 cp2)
|
||
{
|
||
posList.Clear();
|
||
if (posList.Capacity < segment + 1)
|
||
{
|
||
posList.Capacity = segment + 1;
|
||
}
|
||
for (int i = 0; i < segment; i++)
|
||
{
|
||
posList.Add((GetBezier2(i / (float) segment, sp, cp, cp2, ep)));
|
||
}
|
||
posList.Add(ep);
|
||
}
|
||
|
||
public static Vector3 GetBezier(float t, Vector3 sp, Vector3 cp, Vector3 ep)
|
||
{
|
||
Vector3 aa = sp + (cp - sp) * t;
|
||
Vector3 bb = cp + (ep - cp) * t;
|
||
return aa + (bb - aa) * t;
|
||
}
|
||
|
||
public static Vector3 GetBezier2(float t, Vector3 sp, Vector3 p1, Vector3 p2, Vector3 ep)
|
||
{
|
||
t = Mathf.Clamp01(t);
|
||
var oneMinusT = 1f - t;
|
||
return oneMinusT * oneMinusT * oneMinusT * sp +
|
||
3f * oneMinusT * oneMinusT * t * p1 +
|
||
3f * oneMinusT * t * t * p2 +
|
||
t * t * t * ep;
|
||
}
|
||
|
||
public static Vector3 GetDire(float angle, bool isDegree = false)
|
||
{
|
||
angle = isDegree ? angle * Mathf.Deg2Rad : angle;
|
||
return new Vector3(Mathf.Sin(angle), Mathf.Cos(angle));
|
||
}
|
||
|
||
public static Vector3 GetVertialDire(Vector3 dire)
|
||
{
|
||
if (dire.x == 0)
|
||
return new Vector3(-1, 0, 0);
|
||
|
||
if (dire.y == 0)
|
||
return new Vector3(0, -1, 0);
|
||
else
|
||
return new Vector3(-dire.y / dire.x, 1, 0).normalized;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获得0-360的角度(12点钟方向为0度)
|
||
/// </summary>
|
||
/// <param name="from"></param>
|
||
/// <param name="to"></param>
|
||
/// <returns></returns>
|
||
public static float GetAngle360(Vector2 from, Vector2 to)
|
||
{
|
||
float angle;
|
||
|
||
Vector3 cross = Vector3.Cross(from, to);
|
||
angle = Vector2.Angle(from, to);
|
||
angle = cross.z > 0 ? -angle : angle;
|
||
angle = (angle + 360) % 360;
|
||
return angle;
|
||
}
|
||
|
||
public static Vector3 GetPos(Vector3 center, float radius, float angle, bool isDegree = false)
|
||
{
|
||
angle = isDegree ? angle * Mathf.Deg2Rad : angle;
|
||
return new Vector3(center.x + radius * Mathf.Sin(angle),
|
||
center.y + radius * Mathf.Cos(angle));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获得两直线的交点
|
||
/// </summary>
|
||
/// <param name="p1">线段1起点</param>
|
||
/// <param name="p2">线段1终点</param>
|
||
/// <param name="p3">线段2起点</param>
|
||
/// <param name="p4">线段2终点</param>
|
||
/// <param name="intersection">相交点。当不想交时默认为 Vector3.zero </param>
|
||
/// <returns>相交则返回 true, 否则返回 false</returns>
|
||
public static bool GetIntersection(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, ref Vector3 intersection)
|
||
{
|
||
intersection = Vector3.zero;
|
||
|
||
var d = (p2.x - p1.x) * (p4.y - p3.y) - (p2.y - p1.y) * (p4.x - p3.x);
|
||
if (d == 0)
|
||
return false;
|
||
|
||
var u = ((p3.x - p1.x) * (p4.y - p3.y) - (p3.y - p1.y) * (p4.x - p3.x)) / d;
|
||
var v = ((p3.x - p1.x) * (p2.y - p1.y) - (p3.y - p1.y) * (p2.x - p1.x)) / d;
|
||
if (u < 0 || u > 1 || v < 0 || v > 1)
|
||
return false;
|
||
|
||
intersection.x = p1.x + u * (p2.x - p1.x);
|
||
intersection.y = p1.y + u * (p2.y - p1.y);
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 三个点画线段所需要的六个关键点
|
||
/// </summary>
|
||
/// <param name="lp">上一个点</param>
|
||
/// <param name="cp">当前点</param>
|
||
/// <param name="np">下一个点</param>
|
||
/// <param name="width">线段宽度</param>
|
||
/// <param name="ltp">上一个点的上角点</param>
|
||
/// <param name="lbp">上一个点的下角点</param>
|
||
/// <param name="ntp">下一个点的上角点</param>
|
||
/// <param name="nbp">下一个点的下角点</param>
|
||
/// <param name="itp">交汇点的上角点</param>
|
||
/// <param name="ibp">交汇点的下角点</param>
|
||
internal static void GetLinePoints(Vector3 lp, Vector3 cp, Vector3 np, float width,
|
||
ref Vector3 ltp, ref Vector3 lbp,
|
||
ref Vector3 ntp, ref Vector3 nbp,
|
||
ref Vector3 itp, ref Vector3 ibp,
|
||
ref Vector3 clp, ref Vector3 crp,
|
||
ref bool bitp, ref bool bibp, int debugIndex = 0)
|
||
{
|
||
var dir1 = (cp - lp).normalized;
|
||
var dir1v = Vector3.Cross(dir1, Vector3.forward).normalized * width;
|
||
ltp = lp - dir1v;
|
||
lbp = lp + dir1v;
|
||
if (debugIndex == 1 && cp == np)
|
||
{
|
||
ntp = np - dir1v;
|
||
nbp = np + dir1v;
|
||
clp = cp - dir1v;
|
||
crp = cp + dir1v;
|
||
return;
|
||
}
|
||
|
||
var dir2 = (cp - np).normalized;
|
||
var dir2v = Vector3.Cross(dir2, Vector3.back).normalized * width;
|
||
ntp = np - dir2v;
|
||
nbp = np + dir2v;
|
||
clp = cp - dir2v;
|
||
crp = cp + dir2v;
|
||
|
||
if (Vector3.Cross(dir1, dir2) == Vector3.zero && np != cp)
|
||
{
|
||
itp = ntp;
|
||
ibp = nbp;
|
||
return;
|
||
}
|
||
|
||
var ldist = (Vector3.Distance(cp, lp) + 1) * dir1;
|
||
var rdist = (Vector3.Distance(cp, np) + 1) * dir2;
|
||
|
||
bitp = true;
|
||
if (!UGLHelper.GetIntersection(ltp, ltp + ldist, ntp, ntp + rdist, ref itp))
|
||
{
|
||
itp = cp - dir1v;
|
||
clp = cp - dir1v;
|
||
crp = cp - dir2v;
|
||
bitp = false;
|
||
}
|
||
bibp = true;
|
||
if (!UGLHelper.GetIntersection(lbp, lbp + ldist, nbp, nbp + rdist, ref ibp))
|
||
{
|
||
ibp = cp + dir1v;
|
||
clp = cp + dir1v;
|
||
crp = cp + dir2v;
|
||
bibp = false;
|
||
}
|
||
if (bitp == false && bibp == false && cp == np)
|
||
{
|
||
ltp = cp - dir1v;
|
||
clp = cp + dir1v;
|
||
crp = cp + dir1v;
|
||
}
|
||
}
|
||
|
||
public static bool IsPointInTriangle(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 check)
|
||
{
|
||
var dire1 = check - p1;
|
||
var dire2 = check - p2;
|
||
var dire3 = check - p3;
|
||
var c1 = dire1.x * dire2.y - dire1.y * dire2.x;
|
||
var c2 = dire2.x * dire3.y - dire2.y * dire3.x;
|
||
var c3 = dire3.x * dire1.y - dire3.y * dire1.x;
|
||
return c1 * c2 >= 0 && c1 * c3 >= 0;
|
||
}
|
||
|
||
public static bool IsPointInPolygon(Vector3 p, List<Vector3> polyons)
|
||
{
|
||
if (polyons.Count == 0) return false;
|
||
var inside = false;
|
||
var j = polyons.Count - 1;
|
||
for (int i = 0; i < polyons.Count; j = i++)
|
||
{
|
||
var pi = polyons[i];
|
||
var pj = polyons[j];
|
||
if (((pi.y <= p.y && p.y < pj.y) || (pj.y <= p.y && p.y < pi.y)) &&
|
||
(p.x < (pj.x - pi.x) * (p.y - pi.y) / (pj.y - pi.y) + pi.x))
|
||
inside = !inside;
|
||
}
|
||
return inside;
|
||
}
|
||
public static bool IsPointInPolygon(Vector3 p, List<Vector2> polyons)
|
||
{
|
||
if (polyons.Count == 0) return false;
|
||
var inside = false;
|
||
var j = polyons.Count - 1;
|
||
for (int i = 0; i < polyons.Count; j = i++)
|
||
{
|
||
var pi = polyons[i];
|
||
var pj = polyons[j];
|
||
if (((pi.y <= p.y && p.y < pj.y) || (pj.y <= p.y && p.y < pi.y)) &&
|
||
(p.x < (pj.x - pi.x) * (p.y - pi.y) / (pj.y - pi.y) + pi.x))
|
||
inside = !inside;
|
||
}
|
||
return inside;
|
||
}
|
||
}
|
||
} |