rimworld-animation-studio/Library/PackageCache/com.unity.2d.spriteshape@3.0.14/Editor/EditorSpriteGUIUtility.cs
2022-09-13 00:36:34 -05:00

236 lines
9.6 KiB
C#

using UnityEditor;
using UnityEngine;
using UnityEditor.Sprites;
using System.Collections;
using System.Collections.Generic;
namespace UnityEditor.U2D
{
public static class EditorSpriteGUIUtility
{
public enum FitMode
{
BestFit,
FitHorizontal,
FitVertical,
Fill,
Tiled
}
private static Material s_SpriteMaterial;
public static Material spriteMaterial
{
get
{
if (s_SpriteMaterial == null)
{
s_SpriteMaterial = new Material(Shader.Find("Hidden/InternalSpritesInspector"));
s_SpriteMaterial.hideFlags = HideFlags.DontSave;
}
s_SpriteMaterial.SetFloat("_AdjustLinearForGamma", PlayerSettings.colorSpace == ColorSpace.Linear ? 1.0f : 0.0f);
return s_SpriteMaterial;
}
}
public static Texture GetOriginalSpriteTexture(Sprite sprite)
{
return UnityEditor.Sprites.SpriteUtility.GetSpriteTexture(sprite, false);
}
public static Vector2[] GetOriginalSpriteUvs(Sprite sprite)
{
return UnityEditor.Sprites.SpriteUtility.GetSpriteUVs(sprite, false);
}
public static void DrawSpriteInRectPrepare(Rect rect, Sprite sprite, FitMode fitMode, bool excludeBorders, bool forceQuad, Mesh mesh)
{
var vertices = new List<Vector3>();
var uvs = new List<Vector2>();
var indices = new List<int>();
mesh.Clear();
if (!sprite)
{
mesh.UploadMeshData(false);
return;
}
Vector2 scale = Vector2.one;
Rect spriteRect = sprite.textureRect;
Vector2 bottomLeftBorderOffset = sprite.rect.position + new Vector2(sprite.border.x, sprite.border.y) - spriteRect.position;
Vector2 topRightBorderOffset = new Vector2(sprite.border.z, sprite.border.w) + (spriteRect.position + spriteRect.size) - (sprite.rect.position + sprite.rect.size);
if (excludeBorders)
{
forceQuad = true;
spriteRect.position = spriteRect.position + bottomLeftBorderOffset;
spriteRect.size = spriteRect.size - bottomLeftBorderOffset - topRightBorderOffset;
}
bool tiled = false;
if (fitMode == FitMode.Tiled)
{
tiled = true;
forceQuad = true;
fitMode = FitMode.BestFit;
}
if (fitMode == FitMode.BestFit)
{
float spriteRatio = spriteRect.width / spriteRect.height;
float frameRatio = rect.width / rect.height;
if (spriteRatio < frameRatio)
fitMode = FitMode.FitVertical;
else
fitMode = FitMode.FitHorizontal;
}
if (fitMode == FitMode.FitHorizontal)
scale = Vector2.one * (rect.width / spriteRect.width);
if (fitMode == FitMode.FitVertical)
scale = Vector2.one * (rect.height / spriteRect.height);
if (fitMode == FitMode.Fill)
{
scale.x = rect.width / spriteRect.width;
scale.y = rect.height / spriteRect.height;
}
Texture spriteTexture = GetOriginalSpriteTexture(sprite);
if (spriteTexture == null)
return;
if (forceQuad)
{
Vector2 uvScale = new Vector2(1f / spriteTexture.width, 1f / spriteTexture.height);
Vector2 uvPos = Vector2.Scale(spriteRect.position, uvScale);
Vector2 uvSize = Vector2.Scale(spriteRect.size, uvScale);
Vector2 uv0 = uvPos;
Vector2 uv1 = uvPos + Vector2.up * uvSize.y;
Vector2 uv2 = uvPos + Vector2.right * uvSize.x;
Vector2 uv3 = uvPos + uvSize;
Vector3 v0 = new Vector3(uv0.x * spriteTexture.width - spriteRect.position.x - spriteRect.width * 0.5f, uv0.y * spriteTexture.height - spriteRect.position.y - spriteRect.height * 0.5f, 0f);
Vector3 v1 = new Vector3(uv1.x * spriteTexture.width - spriteRect.position.x - spriteRect.width * 0.5f, uv1.y * spriteTexture.height - spriteRect.position.y - spriteRect.height * 0.5f, 0f);
Vector3 v2 = new Vector3(uv2.x * spriteTexture.width - spriteRect.position.x - spriteRect.width * 0.5f, uv2.y * spriteTexture.height - spriteRect.position.y - spriteRect.height * 0.5f, 0f);
Vector3 v3 = new Vector3(uv3.x * spriteTexture.width - spriteRect.position.x - spriteRect.width * 0.5f, uv3.y * spriteTexture.height - spriteRect.position.y - spriteRect.height * 0.5f, 0f);
v0 = Vector3.Scale(v0, scale);
v1 = Vector3.Scale(v1, scale);
v2 = Vector3.Scale(v2, scale);
v3 = Vector3.Scale(v3, scale);
//TODO: Support vertical tiling when horizontal fitted
if (tiled && fitMode == FitMode.FitVertical)
{
Vector2 scaledRectSize = Vector2.Scale(rect.size, new Vector2(1f / scale.x, 1f / scale.y));
float halfDistanceToFill = (scaledRectSize.x - spriteRect.width) * 0.5f;
int halfFillSegmentCount = (int)Mathf.Ceil(halfDistanceToFill / spriteRect.width);
int segmentCount = halfFillSegmentCount * 2 + 1;
int vertexCount = segmentCount * 4;
vertices.Capacity = vertexCount;
uvs.Capacity = vertexCount;
indices.Capacity = vertexCount;
Vector3 offset = Vector3.zero;
Vector3 offsetStep = Vector3.Scale(Vector3.right * spriteRect.width, scale);
float distanceStep = spriteRect.width;
float distanceToFill = halfDistanceToFill + distanceStep;
int vertexIndex = 0;
for (int i = 0; i <= halfFillSegmentCount; ++i)
{
float t = Mathf.Clamp01(distanceToFill / spriteRect.width);
uvs.Add(uv0);
uvs.Add(uv1);
uvs.Add(Vector3.Lerp(uv0, uv2, t));
uvs.Add(Vector3.Lerp(uv1, uv3, t));
vertices.Add(v0 + offset);
vertices.Add(v1 + offset);
vertices.Add(Vector3.Lerp(v0, v2, t) + offset);
vertices.Add(Vector3.Lerp(v1, v3, t) + offset);
indices.Add(vertexIndex);
indices.Add(vertexIndex + 2);
indices.Add(vertexIndex + 1);
indices.Add(vertexIndex + 2);
indices.Add(vertexIndex + 3);
indices.Add(vertexIndex + 1);
vertexIndex += 4;
if (i > 0)
{
uvs.Add(Vector2.Lerp(uv0, uv2, 1f - t));
uvs.Add(Vector2.Lerp(uv1, uv3, 1f - t));
uvs.Add(uv2);
uvs.Add(uv3);
vertices.Add(Vector3.Lerp(v0, v2, 1f - t) - offset);
vertices.Add(Vector3.Lerp(v1, v3, 1f - t) - offset);
vertices.Add(v2 - offset);
vertices.Add(v3 - offset);
indices.Add(vertexIndex);
indices.Add(vertexIndex + 2);
indices.Add(vertexIndex + 1);
indices.Add(vertexIndex + 2);
indices.Add(vertexIndex + 3);
indices.Add(vertexIndex + 1);
vertexIndex += 4;
}
offset += offsetStep;
distanceToFill -= distanceStep;
}
}
else
{
vertices.AddRange(new Vector3[] { v0, v1, v2, v3 });
uvs.AddRange(new Vector2[] { uv0, uv1, uv2, uv3 });
indices.AddRange(new int[] { 0, 2, 1, 2, 3, 1 });
}
}
else
{
ushort[] triangles = sprite.triangles;
indices.Capacity = triangles.Length;
for (int i = 0; i < triangles.Length; ++i)
indices.Add((int)triangles[i]);
uvs.AddRange(GetOriginalSpriteUvs(sprite));
vertices.Capacity = uvs.Count;
for (int i = 0; i < uvs.Count; ++i)
{
Vector3 v = new Vector3(uvs[i].x * spriteTexture.width - spriteRect.position.x - spriteRect.width * 0.5f, uvs[i].y * spriteTexture.height - spriteRect.position.y - spriteRect.height * 0.5f, 0f);
vertices.Add(Vector3.Scale(v, scale));
}
}
mesh.SetVertices(vertices);
mesh.SetUVs(0, uvs);
mesh.SetTriangles(indices, 0);
mesh.UploadMeshData(false);
}
public static void DrawMesh(Mesh mesh, Material material, Vector3 position, Quaternion rotation, Vector3 scale)
{
if (Event.current.type != EventType.Repaint)
return;
Matrix4x4 matrix = new Matrix4x4();
matrix.SetTRS(position, rotation, scale);
material.SetPass(0);
Graphics.DrawMeshNow(mesh, matrix);
}
}
}