using System.Collections.Generic;
using UnityEngine;
using System;
public static class QGlobalFunction
{
public static readonly Vector2 Vector2Center = new Vector2(0.5f, 0.5f);
public static readonly Vector3 Vector3Center = new Vector3(0.5f, 0.5f, 0.5f);
/// <summary>
/// 2D旋转矩阵
/// </summary>
/// <param name="mat"></param>
/// <param name="angle"></param>
/// <returns></returns>
public static Matrix4x4 Rotate2D(this Matrix4x4 mat, float angle)
{
angle = angle * Mathf.Deg2Rad;
mat.m00 = Mathf.Cos(angle);
mat.m01 = Mathf.Sin(angle);
mat.m10 = -Mathf.Sin(angle);
mat.m11 = Mathf.Cos(angle);
return mat;
}
/// <summary>
/// UV旋转
/// </summary>
/// <param name="mesh"></param>
/// <param name="angle"></param>
/// <param name="channelIndex"></param>
/// <returns></returns>
public static Mesh RotateUV(this Mesh mesh, float angle, int channelIndex = 0)
{
List<Vector2> uvs = new List<Vector2>(mesh.uv);
var mat = Rotate2D(new Matrix4x4(), angle);
for (int i = 0; i < uvs.Count; i++)
{
Vector2 uv = uvs[i] - Vector2Center;
uv = (mat * uv);
uv += Vector2Center;
uvs[i] = uv;
}
mesh.SetUVs(channelIndex, uvs);
return mesh;
}
/// <summary>
/// 纹理分割
/// </summary>
/// <param name="target"></param>
/// <param name="rect"></param>
/// <returns></returns>
public static Texture2D TextureClipRect(Texture2D target, RectInt rect)
{
var width = rect.width;
var height = rect.height;
if(rect.x + rect.width >= target.width) width = target.width - rect.x;
if(rect.y + rect.height >= target.height) height = target.height - rect.y;
var result = new Texture2D(width,height);
var data = target.GetPixels(rect.x,rect.y,width,height);
result.SetPixels(data);
result.Apply();
return result;
}
/// <summary>
/// 绘制矩形
/// </summary>
/// <param name="target"></param>
/// <param name="result"></param>
/// <param name="rect"></param>
/// <param name="color"></param>
public static void DrawRect(Texture2D target, ref Texture2D result, RectInt rect, Color color)
{
var data = target.GetPixels();
var width = target.width;
var offsetWidth = rect.width - rect.x;
var offsetHeight = rect.height - rect.y;
if (offsetWidth >= offsetHeight)
{
offsetWidth = rect.x + rect.width;
offsetHeight = rect.y + rect.height;
if (offsetWidth > width) offsetWidth = width;
if (offsetHeight > target.height) offsetHeight = target.height;
for (int y = rect.y; y < offsetHeight; y++)
{
for (int x = rect.x; x < offsetWidth; x++)
{
data[y * width + x] = color;
}
}
}
else
{
offsetWidth = rect.x + rect.width;
offsetHeight = rect.y + rect.height;
if (offsetWidth > width) offsetWidth = width;
if (offsetHeight > target.height) offsetHeight = target.height;
for (int x = rect.x; x < offsetWidth; x++)
{
for (int y = rect.y; y < offsetHeight; y++)
{
data[y * width + x] = color;
}
}
}
result.SetPixels(data);
result.Apply();
}
/// <summary>
/// 绘制矩形
/// </summary>
/// <param name="target"></param>
/// <param name="result"></param>
/// <param name="rect"></param>
/// <param name="coefficient"></param>
public static void DrawRect(Texture2D target, ref Texture2D result, RectInt rect, float coefficient)
{
var data = target.GetPixels();
var width = target.width;
var offsetWidth = rect.width - rect.x;
var offsetHeight = rect.height - rect.y;
Color color;
var w = rect.x + rect.width;
var h = rect.y + rect.height;
if (w > width) w = width;
if (h > target.height) h = target.height;
if (offsetWidth >= offsetHeight)
{
offsetWidth = rect.x + rect.width;
offsetHeight = rect.y + rect.height;
if (offsetWidth > width) offsetWidth = width;
if (offsetHeight > target.height) offsetHeight = target.height;
for (int y = rect.y; y < h; y++)
{
for (int x = rect.x; x < w; x++)
{
color = data[y * width + x];
data[y * width + x] = new Color(color.r * coefficient, color.g * coefficient, color.b * coefficient, color.a);
}
}
}
else
{
offsetWidth = rect.x + rect.width;
offsetHeight = rect.y + rect.height;
if (offsetWidth > width) offsetWidth = width;
if (offsetHeight > target.height) offsetHeight = target.height;
for (int x = rect.x; x < w; x++)
{
for (int y = rect.y; y < h; y++)
{
color = data[y * width + x];
data[y * width + x] = new Color(color.r * coefficient, color.g * coefficient, color.b * coefficient, color.a);
}
}
}
result.SetPixels(data);
result.Apply();
}
/// <summary>
/// 交换值
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
public static void Swap<T>(ref T a, ref T b)
{
var tmp = a;
a = b;
b = tmp;
}
/// <summary>
/// 绘制直角三角形
/// </summary>
/// <param name="target"></param>
/// <param name="result"></param>
/// <param name="color"></param>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <param name="p3"></param>
public static void DrawRightAngleTriangle(Texture2D target, ref Texture2D result, Color color, Vector2Int p1, Vector2Int p2, Vector2Int p3)
{
var data = target.GetPixels();
var width = target.width;
#region 确定 p3
if (p1.y < p2.y) QGlobalFunction.Swap(ref p1, ref p2);
if (p2.y < p3.y) QGlobalFunction.Swap(ref p2, ref p3);
#endregion
#region 确定 p2
if (p1.x < p2.x) QGlobalFunction.Swap(ref p1, ref p2);
#endregion
int count = 0;
Vector2Int[] pos = null;
if (p1.x == p3.x)
{
if (p2.y == p3.y)
{
pos = GetBLinePoints(p2, p1);
}
else
{
pos = GetBLinePoints(p2, p3);
}
Debug.Log(p1 + "" + p2 + p3);
for (int i = 0; i < pos.Length; i++)
{
count = p1.x - pos[i].x;
while (count-- != 0)
{
data[pos[i].y * width + pos[i].x + count] = color;
}
}
}
else
{
if (p1.y == p3.y)
pos = GetBLinePoints(p1, p2);
else
pos = GetBLinePoints(p1, p3);
for (int i = 0; i < pos.Length; i++)
{
count = pos[i].x - p2.x;
while (count-- != 0)
{
data[pos[i].y * width + count + p2.x] = color;
}
}
}
result.SetPixels(data);
result.Apply();
}
public static void DrawRightAngleTriangleTest(Texture2D target, ref Texture2D result)
{
var center = target.height/2;
DrawRightAngleTriangle(target, ref result, Color.green, new Vector2Int(0, 0), new Vector2Int(0, center), new Vector2Int(target.width, center));
DrawRightAngleTriangle(result, ref result, Color.blue, new Vector2Int(0, 0), new Vector2Int(target.width-1, 0), new Vector2Int(target.width-1, center));
DrawRightAngleTriangle(result, ref result, Color.red, new Vector2Int(0, center+1), new Vector2Int(0, target.height-1), new Vector2Int(target.width, target.height-1));
DrawRightAngleTriangle(result, ref result, Color.black, new Vector2Int(0, center+1), new Vector2Int(target.width-1, center+1), new Vector2Int(target.width-1, target.height-1));
}
/// <summary>
/// 绘制直角三角形
/// </summary>
/// <param name="target"></param>
/// <param name="result"></param>
/// <param name="coefficient">系数</param>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <param name="p3"></param>
public static void DrawRightAngleTriangle(Texture2D target, ref Texture2D result, float coefficient, Vector2Int p1, Vector2Int p2, Vector2Int p3)
{
var data = target.GetPixels();
var width = target.width;
#region 确定 p3
if (p1.y < p2.y) Swap(ref p1, ref p2);
if (p2.y < p3.y) Swap(ref p2, ref p3);
#endregion
#region 确定 p2
if (p1.x < p2.x) Swap(ref p1, ref p2);
#endregion
int count = 0;
Vector2Int[] pos = null;
Color color;
int index;
if (p1.x == p3.x)
{
if (p2.y == p3.y)
{
Debug.Log(123 + "" + p1 + p2 + p3);
pos = GetBLinePoints(p2, p1);
}
else
{
Debug.Log(233 + "" + p1 + p2 + p3);
pos = GetBLinePoints(p2, p3);
}
for (int i = 0; i < pos.Length; i++)
{
count = p1.x - pos[i].x;
while (count-- != 0)
{
index = pos[i].y * width + pos[i].x + count;
color = data[index];
data[index] = new Color(color.r * coefficient, color.g * coefficient, color.b * coefficient, color.a);
}
}
}
else
{
if (p1.y == p3.y)
pos = GetBLinePoints(p1, p2);
else
pos = GetBLinePoints(p1, p3);
for (int i = 0; i < pos.Length; i++)
{
count = pos[i].x - p2.x;
while (count-- != 0)
{
index = pos[i].y * width + count + p2.x;
color = data[index];
data[index] = new Color(color.r * coefficient, color.g * coefficient, color.b * coefficient, color.a);
}
}
}
result.SetPixels(data);
result.Apply();
}
/// <summary>
/// 获得直线坐标
/// </summary>
/// <param name="point0"></param>
/// <param name="point1"></param>
/// <returns></returns>
public static Vector2Int[] GetBLinePoints(Vector2Int point0, Vector2Int point1)
{
var points = new List<Vector2Int>();
int x0 = (int)point0.x;
int y0 = (int)point0.y;
int x1 = (int)point1.x;
int y1 = (int)point1.y;
var dx = Math.Abs(x1 - x0);
var dy = Math.Abs(y1 - y0);
var sx = (x0 < x1) ? 1 : -1;
var sy = (y0 < y1) ? 1 : -1;
var err = dx - dy;
int err2;
while (true)
{
points.Add(new Vector2Int(x0, y0));
if ((x0 == x1) && (y0 == y1))
{
break;
}
err2 = 2 * err;
if (err2 + dy > 0)
{
x0 += sx;
err -= dy;
}
if (err2 - dx < 0)
{
y0 += sy;
err += dx;
}
}
return points.ToArray();
}
/// <summary>
/// 绘制直线
/// </summary>
/// <param name="result"></param>
/// <param name="width"></param>
/// <param name="color"></param>
/// <param name="point0"></param>
/// <param name="point1"></param>
public static void DrawBLine(ref Color[] result, int width, Color color, Vector2 point0, Vector2 point1)
{
int x0 = (int)point0.x;
int y0 = (int)point0.y;
int x1 = (int)point1.x;
int y1 = (int)point1.y;
var dx = Math.Abs(x1 - x0);
var dy = Math.Abs(y1 - y0);
var sx = (x0 < x1) ? 1 : -1;
var sy = (y0 < y1) ? 1 : -1;
var err = dx - dy;
int err2;
while (true)
{
result[x0 + y0 * width] = color;
if ((x0 == x1) && (y0 == y1))
{
break;
}
err2 = 2 * err;
if (err2 + dy > 0)
{
x0 += sx;
err -= dy;
}
if (err2 - dx < 0)
{
y0 += sy;
err += dx;
}
}
}
}