unity 扩展方法


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;
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_17813937/article/details/79950879