373 lines
11 KiB
C#
373 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using ProBuilder2.Common;
|
|
using UnityEngine;
|
|
|
|
namespace ProBuilder2.MeshOperations
|
|
{
|
|
// Token: 0x02000005 RID: 5
|
|
public static class pbUVOps
|
|
{
|
|
// Token: 0x0600003A RID: 58 RVA: 0x000063C8 File Offset: 0x000047C8
|
|
public static bool SewUVs(this pb_Object pb, int[] indices, float delta)
|
|
{
|
|
int[] array = new int[indices.Length];
|
|
Vector2[] array2 = pb.uv;
|
|
if (array2 == null || array2.Length != pb.vertexCount)
|
|
{
|
|
array2 = new Vector2[pb.vertexCount];
|
|
}
|
|
for (int i = 0; i < indices.Length; i++)
|
|
{
|
|
array[i] = -(i + 1);
|
|
}
|
|
pb_IntArray[] sharedIndicesUV = pb.sharedIndicesUV;
|
|
for (int j = 0; j < indices.Length - 1; j++)
|
|
{
|
|
for (int k = j + 1; k < indices.Length; k++)
|
|
{
|
|
if (array[j] != array[k])
|
|
{
|
|
if (Vector2.Distance(array2[indices[j]], array2[indices[k]]) < delta)
|
|
{
|
|
Vector3 vector = (array2[indices[j]] + array2[indices[k]]) / 2f;
|
|
array2[indices[j]] = vector;
|
|
array2[indices[k]] = vector;
|
|
int num = pb_IntArrayUtility.MergeSharedIndices(ref sharedIndicesUV, new int[]
|
|
{
|
|
indices[j],
|
|
indices[k]
|
|
});
|
|
array[j] = num;
|
|
array[k] = num;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pb.SetUV(array2);
|
|
pb.SetSharedIndicesUV(sharedIndicesUV);
|
|
return true;
|
|
}
|
|
|
|
// Token: 0x0600003B RID: 59 RVA: 0x00006530 File Offset: 0x00004930
|
|
public static void CollapseUVs(this pb_Object pb, int[] indices)
|
|
{
|
|
Vector2[] uv = pb.uv;
|
|
Vector2 vector = pb_Math.Average(uv.ValuesWithIndices(indices), null);
|
|
foreach (int num in indices)
|
|
{
|
|
uv[num] = vector;
|
|
}
|
|
pb_IntArray[] sharedIndicesUV = pb.sharedIndicesUV;
|
|
pb_IntArrayUtility.MergeSharedIndices(ref sharedIndicesUV, indices);
|
|
pb.SetUV(uv);
|
|
pb.SetSharedIndicesUV(sharedIndicesUV);
|
|
}
|
|
|
|
// Token: 0x0600003C RID: 60 RVA: 0x000065A0 File Offset: 0x000049A0
|
|
public static bool SplitUVs(this pb_Object pb, int[] indices)
|
|
{
|
|
pb_IntArray[] sharedIndicesUV = pb.sharedIndicesUV;
|
|
if (sharedIndicesUV == null)
|
|
{
|
|
return false;
|
|
}
|
|
List<int> list = indices.Distinct<int>().ToList<int>();
|
|
for (int i = 0; i < list.Count; i++)
|
|
{
|
|
int num = sharedIndicesUV.IndexOf(list[i]);
|
|
if (num >= 0)
|
|
{
|
|
sharedIndicesUV[num].array = sharedIndicesUV[num].array.Remove(list[i]);
|
|
}
|
|
}
|
|
foreach (int num2 in list)
|
|
{
|
|
pb_IntArrayUtility.AddValueAtIndex(ref sharedIndicesUV, -1, num2);
|
|
}
|
|
pb.SetSharedIndicesUV(sharedIndicesUV);
|
|
return true;
|
|
}
|
|
|
|
// Token: 0x0600003D RID: 61 RVA: 0x00006670 File Offset: 0x00004A70
|
|
public static void ProjectFacesAuto(pb_Object pb, pb_Face[] faces)
|
|
{
|
|
int[] array = pb_Face.AllTrianglesDistinct(faces);
|
|
Vector3 vector = Vector3.zero;
|
|
foreach (pb_Face pb_Face in faces)
|
|
{
|
|
vector += pb_Math.Normal(pb, pb_Face);
|
|
}
|
|
vector /= (float)faces.Length;
|
|
Vector2[] array2 = pb_Projection.PlanarProject(pb.vertices.ValuesWithIndices(array), vector);
|
|
Vector2[] uv = pb.uv;
|
|
for (int j = 0; j < array.Length; j++)
|
|
{
|
|
uv[array[j]] = array2[j];
|
|
}
|
|
pb.SetUV(uv);
|
|
pb.msh.uv = uv;
|
|
foreach (pb_Face pb_Face2 in faces)
|
|
{
|
|
pb_Face2.elementGroup = -1;
|
|
pb.SplitUVs(pb_Face2.distinctIndices);
|
|
}
|
|
pb.SewUVs(pb_Face.AllTrianglesDistinct(faces), 0.001f);
|
|
}
|
|
|
|
// Token: 0x0600003E RID: 62 RVA: 0x00006774 File Offset: 0x00004B74
|
|
public static void ProjectFacesBox(pb_Object pb, pb_Face[] faces)
|
|
{
|
|
Vector2[] uv = pb.uv;
|
|
Dictionary<ProjectionAxis, List<pb_Face>> dictionary = new Dictionary<ProjectionAxis, List<pb_Face>>();
|
|
for (int i = 0; i < faces.Length; i++)
|
|
{
|
|
Vector3 vector = pb_Math.Normal(pb, faces[i]);
|
|
ProjectionAxis projectionAxis = pb_Projection.VectorToProjectionAxis(vector);
|
|
if (dictionary.ContainsKey(projectionAxis))
|
|
{
|
|
dictionary[projectionAxis].Add(faces[i]);
|
|
}
|
|
else
|
|
{
|
|
dictionary.Add(projectionAxis, new List<pb_Face> { faces[i] });
|
|
}
|
|
faces[i].elementGroup = -1;
|
|
faces[i].manualUV = true;
|
|
}
|
|
foreach (KeyValuePair<ProjectionAxis, List<pb_Face>> keyValuePair in dictionary)
|
|
{
|
|
int[] array = pb_Face.AllTrianglesDistinct(keyValuePair.Value.ToArray());
|
|
Vector2[] array2 = pb_Projection.PlanarProject(pb.vertices.ValuesWithIndices(array), pb_Projection.ProjectionAxisToVector(keyValuePair.Key), keyValuePair.Key, null);
|
|
for (int j = 0; j < array.Length; j++)
|
|
{
|
|
uv[array[j]] = array2[j];
|
|
}
|
|
pb.SplitUVs(array);
|
|
}
|
|
pb.SetUV(uv);
|
|
}
|
|
|
|
// Token: 0x0600003F RID: 63 RVA: 0x000068CC File Offset: 0x00004CCC
|
|
public static void ProjectFacesSphere(pb_Object pb, int[] indices)
|
|
{
|
|
foreach (pb_Face pb_Face in pb.faces)
|
|
{
|
|
if (pb_Face.distinctIndices.ContainsMatch(indices))
|
|
{
|
|
pb_Face.elementGroup = -1;
|
|
pb_Face.manualUV = true;
|
|
}
|
|
}
|
|
pb.SplitUVs(indices);
|
|
Vector2[] array = pb_Projection.SphericalProject(pb.vertices, indices);
|
|
Vector2[] uv = pb.uv;
|
|
for (int j = 0; j < indices.Length; j++)
|
|
{
|
|
uv[indices[j]] = array[j];
|
|
}
|
|
pb.SetUV(uv);
|
|
}
|
|
|
|
// Token: 0x06000040 RID: 64 RVA: 0x00006974 File Offset: 0x00004D74
|
|
public static Vector2[] FitUVs(Vector2[] uvs)
|
|
{
|
|
Vector2 vector = pb_Math.SmallestVector2(uvs);
|
|
for (int i = 0; i < uvs.Length; i++)
|
|
{
|
|
uvs[i] -= vector;
|
|
}
|
|
float num = pb_Math.LargestValue(pb_Math.LargestVector2(uvs));
|
|
for (int i = 0; i < uvs.Length; i++)
|
|
{
|
|
uvs[i] /= num;
|
|
}
|
|
return uvs;
|
|
}
|
|
|
|
// Token: 0x06000041 RID: 65 RVA: 0x000069F0 File Offset: 0x00004DF0
|
|
public static bool AutoStitch(pb_Object pb, pb_Face f1, pb_Face f2)
|
|
{
|
|
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
|
|
for (int i = 0; i < f1.edges.Length; i++)
|
|
{
|
|
int num = f2.edges.IndexOf(f1.edges[i], dictionary);
|
|
if (num > -1)
|
|
{
|
|
pbUVOps.ProjectFacesAuto(pb, new pb_Face[] { f2 });
|
|
f1.manualUV = true;
|
|
f2.manualUV = true;
|
|
f1.textureGroup = -1;
|
|
f2.textureGroup = -1;
|
|
pbUVOps.AlignEdges(pb, f1, f2, f1.edges[i], f2.edges[num]);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Token: 0x06000042 RID: 66 RVA: 0x00006A88 File Offset: 0x00004E88
|
|
private static bool AlignEdges(pb_Object pb, pb_Face f1, pb_Face f2, pb_Edge edge1, pb_Edge edge2)
|
|
{
|
|
Vector2[] uv = pb.uv;
|
|
pb_IntArray[] sharedIndices = pb.sharedIndices;
|
|
pb_IntArray[] sharedIndicesUV = pb.sharedIndicesUV;
|
|
int[] array = new int[] { edge1.x, -1 };
|
|
int[] array2 = new int[] { edge1.y, -1 };
|
|
int num = sharedIndices.IndexOf(edge1.x);
|
|
if (num < 0)
|
|
{
|
|
return false;
|
|
}
|
|
if (sharedIndices[num].array.Contains(edge2.x))
|
|
{
|
|
array[1] = edge2.x;
|
|
array2[1] = edge2.y;
|
|
}
|
|
else
|
|
{
|
|
array[1] = edge2.y;
|
|
array2[1] = edge2.x;
|
|
}
|
|
float num2 = Vector2.Distance(uv[edge1.x], uv[edge1.y]);
|
|
float num3 = Vector2.Distance(uv[edge2.x], uv[edge2.y]);
|
|
float num4 = num2 / num3;
|
|
foreach (int num5 in f2.distinctIndices)
|
|
{
|
|
uv[num5] = uv[num5].ScaleAroundPoint(Vector2.zero, Vector2.one * num4);
|
|
}
|
|
Vector2 vector = (uv[edge1.x] + uv[edge1.y]) / 2f;
|
|
Vector2 vector2 = (uv[edge2.x] + uv[edge2.y]) / 2f;
|
|
Vector2 vector3 = vector - vector2;
|
|
foreach (int num6 in f2.distinctIndices)
|
|
{
|
|
uv[num6] += vector3;
|
|
}
|
|
Vector2 vector4 = uv[array2[0]] - uv[array[0]];
|
|
Vector2 vector5 = uv[array2[1]] - uv[array[1]];
|
|
float num7 = Vector2.Angle(vector4, vector5);
|
|
if (Vector3.Cross(vector4, vector5).z < 0f)
|
|
{
|
|
num7 = 360f - num7;
|
|
}
|
|
foreach (int num8 in f2.distinctIndices)
|
|
{
|
|
uv[num8] = uv[num8].RotateAroundPoint(vector, num7);
|
|
}
|
|
float num9 = Mathf.Abs(Vector2.Distance(uv[array[0]], uv[array[1]])) + Mathf.Abs(Vector2.Distance(uv[array2[0]], uv[array2[1]]));
|
|
if (num9 > 0.02f)
|
|
{
|
|
foreach (int num10 in f2.distinctIndices)
|
|
{
|
|
uv[num10] = uv[num10].RotateAroundPoint(vector, 180f);
|
|
}
|
|
float num11 = Mathf.Abs(Vector2.Distance(uv[array[0]], uv[array[1]])) + Mathf.Abs(Vector2.Distance(uv[array2[0]], uv[array2[1]]));
|
|
if (num11 >= num9)
|
|
{
|
|
foreach (int num12 in f2.distinctIndices)
|
|
{
|
|
uv[num12] = uv[num12].RotateAroundPoint(vector, 180f);
|
|
}
|
|
}
|
|
}
|
|
pb.SplitUVs(f2.distinctIndices);
|
|
pb_IntArrayUtility.MergeSharedIndices(ref sharedIndicesUV, array);
|
|
pb_IntArrayUtility.MergeSharedIndices(ref sharedIndicesUV, array2);
|
|
pb_IntArray.RemoveEmptyOrNull(ref sharedIndicesUV);
|
|
pb.SetSharedIndicesUV(sharedIndicesUV);
|
|
pb.SetUV(uv);
|
|
return true;
|
|
}
|
|
|
|
// Token: 0x06000043 RID: 67 RVA: 0x00006EFC File Offset: 0x000052FC
|
|
public static pb_Transform2D MatchCoordinates(Vector2[] points, Vector2[] target)
|
|
{
|
|
int num = ((points.Length >= target.Length) ? target.Length : points.Length);
|
|
pb_Bounds2D pb_Bounds2D = new pb_Bounds2D(target, num);
|
|
Vector2 vector = pb_Bounds2D.center - pb_Bounds2D.Center(points, num);
|
|
Vector2[] array = new Vector2[points.Length];
|
|
for (int i = 0; i < points.Length; i++)
|
|
{
|
|
array[i] = points[i] + vector;
|
|
}
|
|
Vector2 vector2 = target[1] - target[0];
|
|
Vector2 vector3 = array[1] - array[0];
|
|
float num2 = Vector2.Angle(vector2, vector3);
|
|
float num3 = Vector2.Dot(pb_Math.Perpendicular(vector2), vector3);
|
|
if (num3 < 0f)
|
|
{
|
|
num2 = 360f - num2;
|
|
}
|
|
for (int j = 0; j < points.Length; j++)
|
|
{
|
|
array[j] = array[j].RotateAroundPoint(pb_Bounds2D.center, num2);
|
|
}
|
|
pb_Bounds2D pb_Bounds2D2 = new pb_Bounds2D(array, num);
|
|
Vector2 vector4 = pb_Bounds2D.size.DivideBy(pb_Bounds2D2.size);
|
|
return new pb_Transform2D(vector, num2, vector4);
|
|
}
|
|
|
|
// Token: 0x06000044 RID: 68 RVA: 0x00007054 File Offset: 0x00005454
|
|
public static void SetAutoUV(pb_Object pb, pb_Face[] faces, bool auto)
|
|
{
|
|
if (auto)
|
|
{
|
|
faces = Array.FindAll<pb_Face>(faces, (pb_Face x) => x.manualUV).ToArray<pb_Face>();
|
|
pb.SplitUVs(pb_Face.AllTriangles(faces));
|
|
Vector2[][] array = new Vector2[faces.Length][];
|
|
for (int i = 0; i < faces.Length; i++)
|
|
{
|
|
array[i] = pb.uv.ValuesWithIndices(faces[i].distinctIndices);
|
|
}
|
|
for (int j = 0; j < faces.Length; j++)
|
|
{
|
|
faces[j].uv.Reset();
|
|
faces[j].manualUV = !auto;
|
|
faces[j].elementGroup = -1;
|
|
}
|
|
pb.RefreshUV(faces);
|
|
for (int k = 0; k < faces.Length; k++)
|
|
{
|
|
pb_Transform2D pb_Transform2D = pbUVOps.MatchCoordinates(pb.uv.ValuesWithIndices(faces[k].distinctIndices), array[k]);
|
|
faces[k].uv.offset = -pb_Transform2D.position;
|
|
faces[k].uv.rotation = pb_Transform2D.rotation;
|
|
if (Mathf.Abs(pb_Transform2D.scale.sqrMagnitude - 2f) > 0.1f)
|
|
{
|
|
faces[k].uv.scale = pb_Transform2D.scale;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (pb_Face pb_Face in faces)
|
|
{
|
|
pb_Face.textureGroup = -1;
|
|
pb_Face.manualUV = !auto;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Token: 0x06000045 RID: 69 RVA: 0x000071DC File Offset: 0x000055DC
|
|
public static Vector2 NearestVector2(Vector2 pos, Vector2[] uvs)
|
|
{
|
|
if (uvs.Length < 1)
|
|
{
|
|
return pos;
|
|
}
|
|
Vector2 vector = uvs[0];
|
|
float num = Vector2.Distance(pos, vector);
|
|
for (int i = 1; i < uvs.Length; i++)
|
|
{
|
|
float num2 = Vector2.Distance(pos, uvs[i]);
|
|
if (num2 < num)
|
|
{
|
|
num = num2;
|
|
vector = uvs[i];
|
|
}
|
|
}
|
|
return vector;
|
|
}
|
|
}
|
|
}
|