保存一些代码
using UnityEngine;
public static class Matrix4x4Helper
{
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;
}
}
public static class MeshHelper
{
public static Mesh Rotate2DUV(this Mesh mesh,float angle)
{
List<Vector2> uvs = new List<Vector2>(mesh.uv);
var mat = new Matrix4x4().Rotate2D(angle);
Vector2 uvCenter = new Vector2(0.5f,0.5f);
for(var i=0;i<uvs.Count;i++)
{
var uv = uvs[i]- uvCenter;
uv = (mat * uv);
uvs[i] = uv+ uvCenter;
}
mesh.SetUVs(0, uvs);
return mesh;
}
}
using System;
using UnityEngine;
public class PanelDrag:MonoBehaviour
{
const string mainText = "_MainTex";
[SerializeField] Texture texture;
public Action onMouseDown;
public Action onMouseUp;
Material material;
Vector2Int textureSize;
Vector4 offset;
Vector3 mousePos;
Vector2 size;
Matrix4x4 uvRotate;
float angle;
Matrix4x4 matRotate;
Vector4 actualOffset;
Vector4 textureOffset;
Vector2 textureScale;
Mesh mesh;
Ray ray;
public Texture CurTexture
{
get { return texture; }
set
{
if (value == texture)
return;
UpdateTexture(value);
}
}
private void Start()
{
mesh = GetComponent<MeshFilter>().mesh;
material = GetComponent<MeshRenderer>().material;
UpdateTexture(texture == null ? material.GetTexture(mainText) : texture);
UpdateScale();
}
void UpdateTexture(Texture texture)
{
this.texture = texture;
material.SetTexture(mainText, texture);
textureScale = material.GetTextureScale(mainText);
textureSize = new Vector2Int(texture.width, texture.height);
}
/// <summary>
/// 计算Plane实际大小
/// </summary>
void UpdateScale()
{
var boundsSize = mesh.bounds.size;
size = new Vector2(boundsSize.x, boundsSize.z);
size.Scale(new Vector2(transform.localScale.x, transform.localScale.z));
//mousePos = Vector3.zero;
}
public void RotateUV(float angle)
{
this.angle += angle;
mesh = mesh.Rotate2DUV(angle);
UpdateScale();
UpdateRotateMatrix();
UpdateTextureOffset(Vector3.zero);
//mousePos = Vector3.zero;
}
private void OnMouseDown()
{
onMouseDown();
UpdateScale();
mousePos = GetPanelPos();
UpdateRotateMatrix();
}
private void OnMouseDrag()
{
var pos = GetPanelPos();
UpdateTextureOffset(pos);
mousePos = pos;
}
private void OnMouseUp()
{
onMouseUp();
}
/// <summary>
/// 更新旋转矩阵
/// </summary>
void UpdateRotateMatrix()
{
//获取当前缩放的转置矩阵,逆旋转
matRotate = Matrix4x4.Rotate(transform.localRotation).transpose;
//获取UV旋转矩阵
uvRotate = uvRotate.Rotate2D(angle);
}
void UpdateTextureOffset(Vector3 pos)
{
//获得欧拉角偏移
offset += matRotate * (pos - mousePos);
//设置偏移
actualOffset.Set(offset.x, offset.z, 1, 1);
//旋转UV
actualOffset = uvRotate * actualOffset;
//平移
textureOffset.Set(actualOffset.x * textureScale.x / this.size.x, actualOffset.y * textureScale.y / this.size.y, 1, 1);
//设置图像偏移
material.SetTextureOffset(mainText, textureOffset);
}
/// <summary>
/// 获取从摄像机出发的射线到平面上的点
/// </summary>
/// <returns></returns>
Vector3 GetPanelPos()
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
return GetIntersectWithLineAndPlane(ray.origin, ray.direction, transform.up, transform.position);
}
/// <summary>
/// 获取向量到平面的投影
/// </summary>
/// <param name="point"></param>
/// <param name="direct"></param>
/// <param name="planeNormal"></param>
/// <param name="planePoint"></param>
/// <returns></returns>
private Vector3 GetIntersectWithLineAndPlane(Vector3 point, Vector3 direct, Vector3 planeNormal, Vector3 planePoint)
{
float d = Vector3.Dot(planePoint - point, planeNormal) / Vector3.Dot(direct.normalized, planeNormal);
return d * direct.normalized + point;
}
}