This commit is contained in:
niko
2026-06-04 11:42:34 +02:00
parent f39ba70a9f
commit e720b98cd1
7488 changed files with 2493818 additions and 0 deletions
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using ProBuilder2.Common;
namespace ProBuilder2.MeshOperations
{
// Token: 0x0200000B RID: 11
internal class ConnectFaceRebuildData
{
// Token: 0x06000073 RID: 115 RVA: 0x0000A34D File Offset: 0x0000874D
public ConnectFaceRebuildData(pb_FaceRebuildData faceRebuildData, List<int> newVertexIndices)
{
this.faceRebuildData = faceRebuildData;
this.newVertexIndices = newVertexIndices;
}
// Token: 0x0400001D RID: 29
public pb_FaceRebuildData faceRebuildData;
// Token: 0x0400001E RID: 30
public List<int> newVertexIndices;
}
}
@@ -0,0 +1,905 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using ProBuilder2.Common;
using UnityEngine;
namespace ProBuilder2.MeshOperations
{
// Token: 0x02000002 RID: 2
public static class pbMeshOps
{
// Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000450
public static void CenterPivot(this pb_Object pb, int[] indices)
{
Vector3 vector = Vector3.zero;
if (indices != null && indices.Length > 0)
{
Vector3[] array = pb.VerticesInWorldSpace(indices);
foreach (Vector3 vector2 in array)
{
vector += vector2;
}
vector /= (float)array.Length;
}
else
{
vector = pb.transform.TransformPoint(pb.msh.bounds.center);
}
Vector3 vector3 = pb.transform.position - vector;
pb.transform.position = vector;
pb.ToMesh();
pb.TranslateVertices_World(pb.msh.triangles, vector3);
pb.Refresh(RefreshMask.All);
}
// Token: 0x06000002 RID: 2 RVA: 0x00002120 File Offset: 0x00000520
public static void CenterPivot(this pb_Object pb, Vector3 worldPosition)
{
Vector3 vector = pb.transform.position - worldPosition;
pb.transform.position = worldPosition;
pb.ToMesh();
pb.TranslateVertices_World(pb.msh.triangles, vector);
pb.Refresh(RefreshMask.All);
}
// Token: 0x06000003 RID: 3 RVA: 0x00002170 File Offset: 0x00000570
public static void FreezeScaleTransform(this pb_Object pb)
{
Vector3[] vertices = pb.vertices;
for (int i = 0; i < vertices.Length; i++)
{
vertices[i] = Vector3.Scale(vertices[i], pb.transform.localScale);
}
pb.SetVertices(vertices);
pb.transform.localScale = new Vector3(1f, 1f, 1f);
}
// Token: 0x06000004 RID: 4 RVA: 0x000021E8 File Offset: 0x000005E8
[Obsolete("Please use `bool Extrude(this pb_Object pb, pb_Face[] faces, ExtrudeMethod method, float distance)`")]
public static bool Extrude(this pb_Object pb, pb_Face[] faces, float extrudeDistance)
{
pb_Face[] array;
return pb.Extrude(faces, extrudeDistance, true, out array);
}
// Token: 0x06000005 RID: 5 RVA: 0x00002200 File Offset: 0x00000600
[Obsolete("Please use `bool Extrude(this pb_Object pb, pb_Face[] faces, ExtrudeMethod method, float distance)`")]
public static bool Extrude(this pb_Object pb, pb_Face[] faces, float extrudeDistance, bool extrudeAsGroup, out pb_Face[] appendedFaces)
{
return pb.Extrude(faces, (!extrudeAsGroup) ? ExtrudeMethod.IndividualFaces : ExtrudeMethod.VertexNormal, extrudeDistance, out appendedFaces);
}
// Token: 0x06000006 RID: 6 RVA: 0x0000221C File Offset: 0x0000061C
[Obsolete("Please use `bool Extrude(this pb_Object pb, pb_Face[] faces, ExtrudeMethod method, float distance)`")]
public static bool Extrude(this pb_Object pb, pb_Face[] faces, ExtrudeMethod method, float extrudeDistance, out pb_Face[] appendedFaces)
{
appendedFaces = null;
if (faces == null || faces.Length < 1)
{
return false;
}
pb_IntArray[] sharedIndices = pb.GetSharedIndices();
Dictionary<int, int> dictionary = sharedIndices.ToDictionary();
int vertexCount = pb.vertexCount;
Vector3[] array = pb.vertices;
bool flag = method != ExtrudeMethod.IndividualFaces;
pb_Edge[][] array2;
if (flag)
{
(array2 = new pb_Edge[1][])[0] = pbMeshUtils.GetPerimeterEdges(dictionary, faces).ToArray<pb_Edge>();
}
else
{
array2 = faces.Select((pb_Face x) => x.edges).ToArray<pb_Edge[]>();
}
pb_Edge[][] array3 = array2;
if (array3 == null || array3.Length < 1 || (flag && array3[0].Length < 3))
{
Debug.LogWarning("No perimeter edges found. Try deselecting and reselecting this object and trying again.");
return false;
}
pb_Face[][] array4 = new pb_Face[array3.Length][];
int[][] array5 = new int[array3.Length][];
for (int i = 0; i < array3.Length; i++)
{
int num = 0;
array5[i] = new int[array3[i].Length * 2];
array4[i] = new pb_Face[array3[i].Length];
for (int j = 0; j < array3[i].Length; j++)
{
foreach (pb_Face pb_Face in faces)
{
if (pb_Face.edges.Contains(array3[i][j]))
{
array4[i][j] = pb_Face;
break;
}
}
array5[i][num++] = array3[i][j].x;
array5[i][num++] = array3[i][j].y;
}
}
List<pb_Edge>[] array6 = new List<pb_Edge>[array3.Length];
Vector3[] normals = pb.msh.normals;
Vector3[] array7 = new Vector3[vertexCount];
List<Vector3[]> list = new List<Vector3[]>();
List<Color[]> list2 = new List<Color[]>();
List<Vector2[]> list3 = new List<Vector2[]>();
List<pb_Face> list4 = new List<pb_Face>();
List<int[]> list5 = new List<int[]>();
for (int l = 0; l < array3.Length; l++)
{
array6[l] = new List<pb_Edge>();
for (int m = 0; m < array3[l].Length; m++)
{
pb_Edge pb_Edge = array3[l][m];
pb_Face pb_Face2 = array4[l][m];
Vector3 vector = pb_Math.Normal(pb, pb_Face2);
Vector3 vector2 = Vector3.zero;
Vector3 vector3 = Vector3.zero;
if (Mathf.Abs(extrudeDistance) > Mathf.Epsilon)
{
if (!flag)
{
vector2 = vector;
vector3 = vector;
}
else
{
vector2 = pbMeshOps.Norm(sharedIndices[dictionary[pb_Edge.x]], array5[l], normals);
vector3 = pbMeshOps.Norm(sharedIndices[dictionary[pb_Edge.y]], array5[l], normals);
}
}
int num2 = dictionary[pb_Edge.x];
int num3 = dictionary[pb_Edge.y];
float num4 = extrudeDistance;
float num5 = extrudeDistance;
if (method == ExtrudeMethod.FaceNormal)
{
num4 = pb_Math.Secant(Vector3.Angle(vector, vector2) * 0.017453292f) * extrudeDistance;
num5 = pb_Math.Secant(Vector3.Angle(vector, vector3) * 0.017453292f) * extrudeDistance;
}
array7[pb_Edge.x] = vector2.normalized * num4;
array7[pb_Edge.y] = vector3.normalized * num5;
list.Add(new Vector3[]
{
array[pb_Edge.x],
array[pb_Edge.y],
array[pb_Edge.x] + array7[pb_Edge.x],
array[pb_Edge.y] + array7[pb_Edge.y]
});
list2.Add(new Color[]
{
pb.colors[pb_Edge.x],
pb.colors[pb_Edge.y],
pb.colors[pb_Edge.x],
pb.colors[pb_Edge.y]
});
list3.Add(new Vector2[4]);
list4.Add(new pb_Face(new int[] { 0, 1, 2, 1, 3, 2 }, pb_Face2.material, new pb_UV(pb_Face2.uv), pb_Face2.smoothingGroup, -1, -1, false));
list5.Add(new int[] { num2, num3, -1, -1 });
array6[l].Add(new pb_Edge(num2, -1));
array6[l].Add(new pb_Edge(num3, -1));
}
}
appendedFaces = pb.AppendFaces(list.ToArray(), list2.ToArray(), list3.ToArray(), list4.ToArray(), list5.ToArray());
int n = 0;
int num6 = 0;
while (n < array6.Length)
{
for (int num7 = 0; num7 < array6[n].Count; num7 += 2)
{
array6[n][num7].y = appendedFaces[num6].indices[2];
array6[n][num7 + 1].y = appendedFaces[num6++].indices[4];
}
n++;
}
pb_IntArray[] array8 = pb.sharedIndices;
Dictionary<int, int> dictionary2 = array8.ToDictionary();
for (int num8 = 0; num8 < array6.Length; num8++)
{
for (int num9 = 0; num9 < array6[num8].Count - 1; num9++)
{
int x2 = array6[num8][num9].x;
for (int num10 = num9 + 1; num10 < array6[num8].Count; num10++)
{
if (array6[num8][num10].x == x2)
{
dictionary2[array6[num8][num9].y] = dictionary2[array6[num8][num10].y];
break;
}
}
}
}
array = pb.vertices;
foreach (pb_Face pb_Face3 in faces)
{
pb_Face3.smoothingGroup = -1;
pb_Face3.textureGroup = -1;
}
if (flag)
{
foreach (pb_Face pb_Face4 in faces)
{
int[] distinctIndices = pb_Face4.distinctIndices;
foreach (int num14 in distinctIndices)
{
int num15 = array8.IndexOf(num14);
for (int num16 = 0; num16 < array5.Length; num16++)
{
for (int num17 = 0; num17 < array6[num16].Count; num17++)
{
if (num15 == array6[num16][num17].x)
{
dictionary2[num14] = dictionary2[array6[num16][num17].y];
break;
}
}
}
}
}
}
else
{
for (int num18 = 0; num18 < array4.Length; num18++)
{
int[] array10 = pb_Face.AllTrianglesDistinct(array4[num18]);
for (int num19 = 0; num19 < array10.Length; num19++)
{
int num20 = array10[num19];
int old_si_index = dictionary[num20];
int num21 = array6[num18].FindIndex((pb_Edge x) => x.x == old_si_index);
if (num21 >= 0)
{
int y = array6[num18][num21].y;
if (dictionary2.ContainsKey(y))
{
dictionary2[num20] = dictionary2[y];
}
}
}
}
}
array8 = dictionary2.ToSharedIndices();
pb.SplitUVs(pb_Face.AllTriangles(faces));
int[] array11 = pb_Face.AllTrianglesDistinct(faces);
float num22 = extrudeDistance;
foreach (pb_Face pb_Face5 in faces)
{
Vector3 vector4 = pb_Math.Normal(array[pb_Face5.indices[0]], array[pb_Face5.indices[1]], array[pb_Face5.indices[2]]);
Vector3 vector5 = ((!flag) ? vector4 : Vector3.zero);
foreach (int num25 in pb_Face5.distinctIndices)
{
if (flag)
{
vector5 = pbMeshOps.Norm(sharedIndices[dictionary[num25]], array11, normals);
if (method == ExtrudeMethod.FaceNormal)
{
num22 = pb_Math.Secant(Vector3.Angle(vector4, vector5) * 0.017453292f) * extrudeDistance;
}
}
array[num25] += vector5.normalized * num22;
}
}
pb.SetSharedIndices(array8);
pb.SetVertices(array);
List<pb_Face> list6 = new List<pb_Face>(appendedFaces);
list6.AddRange(faces);
HashSet<pb_Face> hashSet = new HashSet<pb_Face>(faces);
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, list6, false, null);
foreach (pb_WingedEdge pb_WingedEdge in wingedEdges)
{
if (hashSet.Contains(pb_WingedEdge.face))
{
hashSet.Remove(pb_WingedEdge.face);
pb_WingedEdgeEnumerator enumerator2 = pb_WingedEdge.GetEnumerator();
try
{
while (enumerator2.MoveNext())
{
pb_WingedEdge pb_WingedEdge2 = enumerator2.Current;
pb_ConformNormals.ConformOppositeNormal(pb_WingedEdge2);
}
}
finally
{
IDisposable disposable;
if ((disposable = enumerator2 as IDisposable) != null)
{
disposable.Dispose();
}
}
}
}
return true;
}
// Token: 0x06000007 RID: 7 RVA: 0x00002CBC File Offset: 0x000010BC
private static Vector3 Norm(int[] shared, int[] all, Vector3[] norm)
{
Vector3 vector = Vector3.zero;
int num = 0;
for (int i = 0; i < all.Length; i++)
{
if (Array.IndexOf<int>(shared, all[i]) > -1)
{
vector += norm[all[i]];
num++;
}
}
return vector / (float)num;
}
// Token: 0x06000008 RID: 8 RVA: 0x00002D18 File Offset: 0x00001118
public static bool Extrude(this pb_Object pb, pb_Edge[] edges, float extrudeDistance, bool extrudeAsGroup, bool enableManifoldExtrude, out pb_Edge[] extrudedEdges)
{
pb_IntArray[] array = pb.sharedIndices;
Dictionary<int, int> dictionary = array.ToDictionary();
List<pb_Edge> list = new List<pb_Edge>();
List<pb_Face> list2 = new List<pb_Face>();
foreach (pb_Edge pb_Edge in edges)
{
int num = 0;
pb_Face pb_Face = null;
foreach (pb_Face pb_Face2 in pb.faces)
{
if (pb_Face2.edges.IndexOf(pb_Edge, dictionary) > -1)
{
pb_Face = pb_Face2;
if (++num > 1)
{
break;
}
}
}
if (enableManifoldExtrude || num < 2)
{
list.Add(pb_Edge);
list2.Add(pb_Face);
}
}
if (list.Count < 1)
{
extrudedEdges = null;
return false;
}
Vector3[] vertices = pb.vertices;
Vector3[] normals = pb.msh.normals;
int[] array2 = new int[list.Count * 2];
int num2 = 0;
for (int k = 0; k < list.Count; k++)
{
array2[num2++] = list[k].x;
array2[num2++] = list[k].y;
}
List<pb_Edge> list3 = new List<pb_Edge>();
List<pb_Edge> list4 = new List<pb_Edge>();
for (int l = 0; l < list.Count; l++)
{
pb_Edge pb_Edge2 = list[l];
pb_Face pb_Face3 = list2[l];
Vector3 vector = ((!extrudeAsGroup) ? pb_Math.Normal(pb, pb_Face3) : pbMeshOps.Norm(array[dictionary[pb_Edge2.x]], array2, normals));
Vector3 vector2 = ((!extrudeAsGroup) ? pb_Math.Normal(pb, pb_Face3) : pbMeshOps.Norm(array[dictionary[pb_Edge2.y]], array2, normals));
int num3 = dictionary[pb_Edge2.x];
int num4 = dictionary[pb_Edge2.y];
pb_Face pb_Face4 = pb.AppendFace(new Vector3[]
{
vertices[pb_Edge2.x],
vertices[pb_Edge2.y],
vertices[pb_Edge2.x] + vector.normalized * extrudeDistance,
vertices[pb_Edge2.y] + vector2.normalized * extrudeDistance
}, new Color[]
{
pb.colors[pb_Edge2.x],
pb.colors[pb_Edge2.y],
pb.colors[pb_Edge2.x],
pb.colors[pb_Edge2.y]
}, new Vector2[4], new pb_Face(new int[] { 2, 1, 0, 2, 3, 1 }, pb_Face3.material, new pb_UV(), 0, -1, -1, false), new int[] { num3, num4, -1, -1 });
list4.Add(new pb_Edge(pb_Face4.indices[3], pb_Face4.indices[4]));
list3.Add(new pb_Edge(num3, pb_Face4.indices[3]));
list3.Add(new pb_Edge(num4, pb_Face4.indices[4]));
}
array = pb.sharedIndices;
if (extrudeAsGroup)
{
for (int m = 0; m < list3.Count; m++)
{
int x = list3[m].x;
for (int n = 0; n < list3.Count; n++)
{
if (n != m)
{
if (list3[n].x == x)
{
pb_IntArrayUtility.MergeSharedIndices(ref array, list3[n].y, list3[m].y);
break;
}
}
}
}
}
pb.SetSharedIndices(array);
foreach (pb_Face pb_Face5 in pb.faces)
{
pb_Face5.RebuildCaches();
}
extrudedEdges = list4.ToArray();
return true;
}
// Token: 0x06000009 RID: 9 RVA: 0x000031CC File Offset: 0x000015CC
public static List<pb_Face> DetachFaces(this pb_Object pb, IEnumerable<pb_Face> faces)
{
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
int num = pb.sharedIndices.Length;
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
List<pb_FaceRebuildData> list2 = new List<pb_FaceRebuildData>();
foreach (pb_Face pb_Face in faces)
{
pb_FaceRebuildData pb_FaceRebuildData = new pb_FaceRebuildData();
pb_FaceRebuildData.vertices = new List<pb_Vertex>();
pb_FaceRebuildData.sharedIndices = new List<int>();
pb_FaceRebuildData.face = new pb_Face(pb_Face);
Dictionary<int, int> dictionary2 = new Dictionary<int, int>();
int[] array = new int[pb_Face.indices.Length];
for (int i = 0; i < pb_Face.indices.Length; i++)
{
int count;
if (dictionary2.TryGetValue(pb_Face.indices[i], out count))
{
array[i] = count;
}
else
{
count = pb_FaceRebuildData.vertices.Count;
array[i] = count;
dictionary2.Add(pb_Face.indices[i], count);
pb_FaceRebuildData.vertices.Add(list[pb_Face.indices[i]]);
pb_FaceRebuildData.sharedIndices.Add(dictionary[pb_Face.indices[i]] + num);
}
}
pb_FaceRebuildData.face.SetIndices(array.ToArray<int>());
list2.Add(pb_FaceRebuildData);
}
pb_FaceRebuildData.Apply(list2, pb, list, null, dictionary, null);
pb.DeleteFaces(faces);
pb.ToMesh();
return list2.Select((pb_FaceRebuildData x) => x.face).ToList<pb_Face>();
}
// Token: 0x0600000A RID: 10 RVA: 0x00003398 File Offset: 0x00001798
public static bool Bridge(this pb_Object pb, pb_Edge a, pb_Edge b, bool enforcePerimiterEdgesOnly = false)
{
pb_IntArray[] sharedIndices = pb.GetSharedIndices();
Dictionary<int, int> dictionary = sharedIndices.ToDictionary();
if (enforcePerimiterEdgesOnly && (pbMeshUtils.GetNeighborFaces(pb, a, null).Count > 1 || pbMeshUtils.GetNeighborFaces(pb, b, null).Count > 1))
{
return false;
}
foreach (pb_Face pb_Face in pb.faces)
{
if (pb_Face.edges.IndexOf(a, dictionary) >= 0 && pb_Face.edges.IndexOf(b, dictionary) >= 0)
{
Debug.LogWarning("Face already exists between these two edges!");
return false;
}
}
Vector3[] vertices = pb.vertices;
pb_UV pb_UV = new pb_UV();
Material material = pb_Constant.DefaultMaterial;
pb_Tuple<pb_Face, pb_Edge> pb_Tuple = null;
if (!pb_Edge.ValidateEdge(pb, a, out pb_Tuple))
{
pb_Edge.ValidateEdge(pb, b, out pb_Tuple);
}
if (pb_Tuple != null)
{
pb_UV = new pb_UV(pb_Tuple.Item1.uv);
material = pb_Tuple.Item1.material;
}
Vector3[] array;
Color[] array2;
int[] array3;
if (a.Contains(b.x, sharedIndices) || a.Contains(b.y, sharedIndices))
{
array = new Vector3[3];
array2 = new Color[3];
array3 = new int[3];
bool flag = Array.IndexOf<int>(sharedIndices[sharedIndices.IndexOf(a.x)], b.x) > -1;
bool flag2 = Array.IndexOf<int>(sharedIndices[sharedIndices.IndexOf(a.x)], b.y) > -1;
bool flag3 = Array.IndexOf<int>(sharedIndices[sharedIndices.IndexOf(a.y)], b.x) > -1;
bool flag4 = Array.IndexOf<int>(sharedIndices[sharedIndices.IndexOf(a.y)], b.y) > -1;
if (flag)
{
array[0] = vertices[a.x];
array2[0] = pb.colors[a.x];
array3[0] = sharedIndices.IndexOf(a.x);
array[1] = vertices[a.y];
array2[1] = pb.colors[a.y];
array3[1] = sharedIndices.IndexOf(a.y);
array[2] = vertices[b.y];
array2[2] = pb.colors[b.y];
array3[2] = sharedIndices.IndexOf(b.y);
}
else if (flag2)
{
array[0] = vertices[a.x];
array2[0] = pb.colors[a.x];
array3[0] = sharedIndices.IndexOf(a.x);
array[1] = vertices[a.y];
array2[1] = pb.colors[a.y];
array3[1] = sharedIndices.IndexOf(a.y);
array[2] = vertices[b.x];
array2[2] = pb.colors[b.x];
array3[2] = sharedIndices.IndexOf(b.x);
}
else if (flag3)
{
array[0] = vertices[a.y];
array2[0] = pb.colors[a.y];
array3[0] = sharedIndices.IndexOf(a.y);
array[1] = vertices[a.x];
array2[1] = pb.colors[a.x];
array3[1] = sharedIndices.IndexOf(a.x);
array[2] = vertices[b.y];
array2[2] = pb.colors[b.y];
array3[2] = sharedIndices.IndexOf(b.y);
}
else if (flag4)
{
array[0] = vertices[a.y];
array2[0] = pb.colors[a.y];
array3[0] = sharedIndices.IndexOf(a.y);
array[1] = vertices[a.x];
array2[1] = pb.colors[a.x];
array3[1] = sharedIndices.IndexOf(a.x);
array[2] = vertices[b.x];
array2[2] = pb.colors[b.x];
array3[2] = sharedIndices.IndexOf(b.x);
}
Vector3[] array4 = array;
Color[] array5 = array2;
Vector2[] array6 = new Vector2[array.Length];
int[] array8;
if (flag || flag2)
{
int[] array7 = new int[3];
array7[0] = 2;
array8 = array7;
array7[1] = 1;
}
else
{
int[] array9 = new int[3];
array9[1] = 1;
array8 = array9;
array9[2] = 2;
}
pb.AppendFace(array4, array5, array6, new pb_Face(array8, material, pb_UV, 0, -1, -1, false), array3);
return true;
}
array = new Vector3[4];
array2 = new Color[4];
array3 = new int[4];
array[0] = vertices[a.x];
array2[0] = pb.colors[a.x];
array3[0] = sharedIndices.IndexOf(a.x);
array[1] = vertices[a.y];
array2[1] = pb.colors[a.y];
array3[1] = sharedIndices.IndexOf(a.y);
Vector3 normalized = Vector3.Cross(vertices[b.x] - vertices[a.x], vertices[a.y] - vertices[a.x]).normalized;
Vector2[] array10 = pb_Projection.PlanarProject(new Vector3[]
{
vertices[a.x],
vertices[a.y],
vertices[b.x],
vertices[b.y]
}, normalized);
Vector2 zero = Vector2.zero;
if (!pb_Math.GetLineSegmentIntersect(array10[0], array10[2], array10[1], array10[3], ref zero))
{
array[2] = vertices[b.x];
array2[2] = pb.colors[b.x];
array3[2] = sharedIndices.IndexOf(b.x);
array[3] = vertices[b.y];
array2[3] = pb.colors[b.y];
array3[3] = sharedIndices.IndexOf(b.y);
}
else
{
array[2] = vertices[b.y];
array2[2] = pb.colors[b.y];
array3[2] = sharedIndices.IndexOf(b.y);
array[3] = vertices[b.x];
array2[3] = pb.colors[b.x];
array3[3] = sharedIndices.IndexOf(b.x);
}
pb.AppendFace(array, array2, new Vector2[array.Length], new pb_Face(new int[] { 2, 1, 0, 2, 3, 1 }, material, pb_UV, 0, -1, -1, false), array3);
return true;
}
// Token: 0x0600000B RID: 11 RVA: 0x00003D24 File Offset: 0x00002124
public static bool CombineObjects(pb_Object[] pbs, out pb_Object combined)
{
combined = null;
if (pbs.Length < 1)
{
return false;
}
List<Vector3> list = new List<Vector3>();
List<Vector2> list2 = new List<Vector2>();
List<Color> list3 = new List<Color>();
List<pb_Face> list4 = new List<pb_Face>();
List<pb_IntArray> list5 = new List<pb_IntArray>();
List<pb_IntArray> list6 = new List<pb_IntArray>();
foreach (pb_Object pb_Object in pbs)
{
int count = list.Count;
list.AddRange(pb_Object.VerticesInWorldSpace());
list2.AddRange(pb_Object.uv);
list3.AddRange(pb_Object.colors);
pb_Face[] array = new pb_Face[pb_Object.faces.Length];
for (int j = 0; j < array.Length; j++)
{
array[j] = new pb_Face(pb_Object.faces[j]);
array[j].manualUV = true;
array[j].ShiftIndices(count);
array[j].RebuildCaches();
}
list4.AddRange(array);
pb_IntArray[] sharedIndices = pb_Object.GetSharedIndices();
for (int k = 0; k < sharedIndices.Length; k++)
{
for (int l = 0; l < sharedIndices[k].Length; l++)
{
pb_IntArray pb_IntArray;
int num;
(pb_IntArray = sharedIndices[k])[num = l] = pb_IntArray[num] + count;
}
}
list5.AddRange(sharedIndices);
pb_IntArray[] sharedIndicesUV = pb_Object.GetSharedIndicesUV();
for (int m = 0; m < sharedIndicesUV.Length; m++)
{
for (int n = 0; n < sharedIndicesUV[m].Length; n++)
{
pb_IntArray pb_IntArray;
int num2;
(pb_IntArray = sharedIndicesUV[m])[num2 = n] = pb_IntArray[num2] + count;
}
}
list6.AddRange(sharedIndicesUV);
}
GameObject gameObject = global::UnityEngine.Object.Instantiate<GameObject>(pbs[0].gameObject);
gameObject.transform.position = Vector3.zero;
gameObject.transform.localRotation = Quaternion.identity;
gameObject.transform.localScale = Vector3.one;
IEnumerator enumerator = gameObject.transform.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
object obj = enumerator.Current;
Transform transform = (Transform)obj;
global::UnityEngine.Object.DestroyImmediate(transform.gameObject);
}
}
finally
{
IDisposable disposable;
if ((disposable = enumerator as IDisposable) != null)
{
disposable.Dispose();
}
}
if (gameObject.GetComponent<pb_Object>())
{
global::UnityEngine.Object.DestroyImmediate(gameObject.GetComponent<pb_Object>());
}
if (gameObject.GetComponent<pb_Entity>())
{
global::UnityEngine.Object.DestroyImmediate(gameObject.GetComponent<pb_Entity>());
}
combined = gameObject.AddComponent<pb_Object>();
combined.SetVertices(list.ToArray());
combined.SetUV(list2.ToArray());
combined.SetColors(list3.ToArray());
combined.SetFaces(list4.ToArray());
combined.SetSharedIndices(list5.ToArray() ?? pb_IntArrayUtility.ExtractSharedIndices(list.ToArray()));
combined.SetSharedIndicesUV(list6.ToArray() ?? new pb_IntArray[0]);
combined.ToMesh();
combined.GetComponent<pb_Entity>().SetEntity(pbs[0].GetComponent<pb_Entity>().entityType);
combined.CenterPivot(pbs[0].transform.position);
combined.Refresh(RefreshMask.All);
foreach (pb_Object pb_Object2 in pbs)
{
pb_Object2.Verify();
}
return true;
}
// Token: 0x0600000C RID: 12 RVA: 0x000040B4 File Offset: 0x000024B4
public static pb_Object CreatePbObjectWithTransform(Transform t, bool preserveFaces)
{
Mesh sharedMesh = t.GetComponent<MeshFilter>().sharedMesh;
Vector3[] meshAttribute = pb_MeshUtility.GetMeshAttribute<Vector3[]>(t.gameObject, (Mesh x) => x.vertices);
Color[] meshAttribute2 = pb_MeshUtility.GetMeshAttribute<Color[]>(t.gameObject, (Mesh x) => x.colors);
Vector2[] meshAttribute3 = pb_MeshUtility.GetMeshAttribute<Vector2[]>(t.gameObject, (Mesh x) => x.uv);
List<Vector3> list = ((!preserveFaces) ? new List<Vector3>() : new List<Vector3>(sharedMesh.vertices));
List<Color> list2 = ((!preserveFaces) ? new List<Color>() : new List<Color>(sharedMesh.colors));
List<Vector2> list3 = ((!preserveFaces) ? new List<Vector2>() : new List<Vector2>(sharedMesh.uv));
List<pb_Face> list4 = new List<pb_Face>();
for (int i = 0; i < sharedMesh.subMeshCount; i++)
{
int[] triangles = sharedMesh.GetTriangles(i);
for (int j = 0; j < triangles.Length; j += 3)
{
int num = -1;
if (preserveFaces)
{
for (int k = 0; k < list4.Count; k++)
{
if (list4[k].distinctIndices.Contains(triangles[j]) || list4[k].distinctIndices.Contains(triangles[j + 1]) || list4[k].distinctIndices.Contains(triangles[j + 2]))
{
num = k;
break;
}
}
}
if (num > -1 && preserveFaces)
{
int num2 = list4[num].indices.Length;
int[] array = new int[num2 + 3];
Array.Copy(list4[num].indices, 0, array, 0, num2);
array[num2] = triangles[j];
array[num2 + 1] = triangles[j + 1];
array[num2 + 2] = triangles[j + 2];
list4[num].SetIndices(array);
list4[num].RebuildCaches();
}
else
{
int[] array2;
if (preserveFaces)
{
array2 = new int[]
{
triangles[j],
triangles[j + 1],
triangles[j + 2]
};
}
else
{
list.Add(meshAttribute[triangles[j]]);
list.Add(meshAttribute[triangles[j + 1]]);
list.Add(meshAttribute[triangles[j + 2]]);
list2.Add((meshAttribute2 == null) ? Color.white : meshAttribute2[triangles[j]]);
list2.Add((meshAttribute2 == null) ? Color.white : meshAttribute2[triangles[j + 1]]);
list2.Add((meshAttribute2 == null) ? Color.white : meshAttribute2[triangles[j + 2]]);
list3.Add(meshAttribute3[triangles[j]]);
list3.Add(meshAttribute3[triangles[j + 1]]);
list3.Add(meshAttribute3[triangles[j + 2]]);
array2 = new int[]
{
j,
j + 1,
j + 2
};
}
list4.Add(new pb_Face(array2, t.GetComponent<MeshRenderer>().sharedMaterials[i], new pb_UV(), 0, -1, -1, true));
}
}
}
GameObject gameObject = global::UnityEngine.Object.Instantiate<GameObject>(t.gameObject);
gameObject.GetComponent<MeshFilter>().sharedMesh = null;
pb_Object pb_Object = gameObject.AddComponent<pb_Object>();
pb_Object.GeometryWithVerticesFaces(list.ToArray(), list4.ToArray());
pb_Object.SetColors(list2.ToArray());
pb_Object.SetUV(list3.ToArray());
pb_Object.gameObject.name = t.name;
gameObject.transform.position = t.position;
gameObject.transform.localRotation = t.localRotation;
gameObject.transform.localScale = t.localScale;
pb_Object.CenterPivot(null);
return pb_Object;
}
// Token: 0x0600000D RID: 13 RVA: 0x0000451C File Offset: 0x0000291C
public static bool ResetPbObjectWithMeshFilter(pb_Object pb, bool preserveFaces)
{
MeshFilter component = pb.gameObject.GetComponent<MeshFilter>();
if (component == null || component.sharedMesh == null)
{
pb_Log.Error(pb.name + " does not have a mesh or Mesh Filter component.");
return false;
}
Mesh sharedMesh = component.sharedMesh;
int vertexCount = sharedMesh.vertexCount;
Vector3[] meshAttribute = pb_MeshUtility.GetMeshAttribute<Vector3[]>(pb.gameObject, (Mesh x) => x.vertices);
Color[] meshAttribute2 = pb_MeshUtility.GetMeshAttribute<Color[]>(pb.gameObject, (Mesh x) => x.colors);
Vector2[] meshAttribute3 = pb_MeshUtility.GetMeshAttribute<Vector2[]>(pb.gameObject, (Mesh x) => x.uv);
List<Vector3> list = ((!preserveFaces) ? new List<Vector3>() : new List<Vector3>(sharedMesh.vertices));
List<Color> list2 = ((!preserveFaces) ? new List<Color>() : new List<Color>(sharedMesh.colors));
List<Vector2> list3 = ((!preserveFaces) ? new List<Vector2>() : new List<Vector2>(sharedMesh.uv));
List<pb_Face> list4 = new List<pb_Face>();
MeshRenderer meshRenderer = pb.gameObject.GetComponent<MeshRenderer>();
if (meshRenderer == null)
{
meshRenderer = pb.gameObject.AddComponent<MeshRenderer>();
}
Material[] sharedMaterials = meshRenderer.sharedMaterials;
int num = sharedMaterials.Length;
for (int i = 0; i < sharedMesh.subMeshCount; i++)
{
int[] triangles = sharedMesh.GetTriangles(i);
for (int j = 0; j < triangles.Length; j += 3)
{
int num2 = -1;
if (preserveFaces)
{
for (int k = 0; k < list4.Count; k++)
{
if (list4[k].distinctIndices.Contains(triangles[j]) || list4[k].distinctIndices.Contains(triangles[j + 1]) || list4[k].distinctIndices.Contains(triangles[j + 2]))
{
num2 = k;
break;
}
}
}
if (num2 > -1 && preserveFaces)
{
int num3 = list4[num2].indices.Length;
int[] array = new int[num3 + 3];
Array.Copy(list4[num2].indices, 0, array, 0, num3);
array[num3] = triangles[j];
array[num3 + 1] = triangles[j + 1];
array[num3 + 2] = triangles[j + 2];
list4[num2].SetIndices(array);
list4[num2].RebuildCaches();
}
else
{
int[] array2;
if (preserveFaces)
{
array2 = new int[]
{
triangles[j],
triangles[j + 1],
triangles[j + 2]
};
}
else
{
list.Add(meshAttribute[triangles[j]]);
list.Add(meshAttribute[triangles[j + 1]]);
list.Add(meshAttribute[triangles[j + 2]]);
list2.Add((meshAttribute2 == null || meshAttribute2.Length != vertexCount) ? Color.white : meshAttribute2[triangles[j]]);
list2.Add((meshAttribute2 == null || meshAttribute2.Length != vertexCount) ? Color.white : meshAttribute2[triangles[j + 1]]);
list2.Add((meshAttribute2 == null || meshAttribute2.Length != vertexCount) ? Color.white : meshAttribute2[triangles[j + 2]]);
list3.Add(meshAttribute3[triangles[j]]);
list3.Add(meshAttribute3[triangles[j + 1]]);
list3.Add(meshAttribute3[triangles[j + 2]]);
array2 = new int[]
{
j,
j + 1,
j + 2
};
}
list4.Add(new pb_Face(array2, sharedMaterials[(i < num) ? i : (num - 1)], new pb_UV(), 0, -1, -1, true));
}
}
}
pb.SetVertices(list.ToArray());
pb.SetUV(list3.ToArray());
pb.SetFaces(list4.ToArray());
pb.SetSharedIndices(pb_IntArrayUtility.ExtractSharedIndices(list.ToArray()));
pb.SetColors(list2.ToArray());
return true;
}
}
}
@@ -0,0 +1,570 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ProBuilder2.Common;
namespace ProBuilder2.MeshOperations
{
// Token: 0x02000003 RID: 3
public class pbMeshUtils
{
// Token: 0x06000017 RID: 23 RVA: 0x00004A30 File Offset: 0x00002E30
public static List<pb_Face> GetNeighborFaces(pb_Object pb, pb_Face originFace, Dictionary<int, int> lookup = null, IEnumerable<pb_Face> mask = null)
{
if (lookup == null)
{
lookup = pb.sharedIndices.ToDictionary();
}
List<pb_Face> list = new List<pb_Face>();
HashSet<pb_Edge> hashSet = new HashSet<pb_Edge>();
for (int i = 0; i < originFace.edges.Length; i++)
{
hashSet.Add(new pb_Edge(lookup[originFace.edges[i].x], lookup[originFace.edges[i].y]));
}
pb_Edge pb_Edge = new pb_Edge(-1, -1);
for (int j = 0; j < pb.faces.Length; j++)
{
foreach (pb_Edge pb_Edge2 in pb.faces[j].edges)
{
pb_Edge.x = lookup[pb_Edge2.x];
pb_Edge.y = lookup[pb_Edge2.y];
bool flag = hashSet.Contains(pb_Edge);
if (flag && (mask == null || !mask.Contains(pb.faces[j])))
{
list.Add(pb.faces[j]);
break;
}
}
}
return list;
}
// Token: 0x06000018 RID: 24 RVA: 0x00004B64 File Offset: 0x00002F64
public static Dictionary<pb_Face, List<pb_Face>> GenerateNeighborLookup(pb_Object pb, IList<pb_Face> InFaces)
{
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
Dictionary<pb_Face, List<pb_Face>> dictionary2 = new Dictionary<pb_Face, List<pb_Face>>();
int num = InFaces.Count<pb_Face>();
HashSet<pb_Edge>[] array = new HashSet<pb_Edge>[num];
for (int i = 0; i < num; i++)
{
array[i] = new HashSet<pb_Edge>(pb_Edge.GetUniversalEdges(InFaces[i].edges, dictionary));
}
for (int j = 0; j < num - 1; j++)
{
if (!dictionary2.ContainsKey(InFaces[j]))
{
dictionary2.Add(InFaces[j], new List<pb_Face>());
}
for (int k = j + 1; k < num; k++)
{
bool flag = array[j].Overlaps(array[k]);
if (flag)
{
dictionary2[InFaces[j]].Add(InFaces[k]);
List<pb_Face> list;
if (dictionary2.TryGetValue(InFaces[k], out list))
{
list.Add(InFaces[j]);
}
else
{
dictionary2.Add(InFaces[k], new List<pb_Face> { InFaces[j] });
}
}
}
}
return dictionary2;
}
// Token: 0x06000019 RID: 25 RVA: 0x00004CA4 File Offset: 0x000030A4
public static pb_Face[] GetNeighborFaces(pb_Object pb, Dictionary<int, int> sharedIndicesLookup, pb_Face[] selFaces)
{
List<pb_Face> list = new List<pb_Face>();
pb_Edge[] array = pbMeshUtils.GetPerimeterEdges(sharedIndicesLookup, selFaces).ToArray<pb_Edge>();
pb_Edge[] array2 = new pb_Edge[array.Length];
for (int i = 0; i < array.Length; i++)
{
array2[i] = new pb_Edge(sharedIndicesLookup[array[i].x], sharedIndicesLookup[array[i].y]);
}
pb_Edge pb_Edge = new pb_Edge(-1, -1);
HashSet<pb_Face> hashSet = new HashSet<pb_Face>(selFaces);
foreach (pb_Face pb_Face in pb.faces)
{
if (hashSet.Contains(pb_Face))
{
hashSet.Remove(pb_Face);
}
else
{
foreach (pb_Edge pb_Edge2 in pb_Face.edges)
{
pb_Edge.x = sharedIndicesLookup[pb_Edge2.x];
pb_Edge.y = sharedIndicesLookup[pb_Edge2.y];
if (array2.Contains(pb_Edge))
{
list.Add(pb_Face);
break;
}
}
}
}
return list.ToArray();
}
// Token: 0x0600001A RID: 26 RVA: 0x00004DCC File Offset: 0x000031CC
public static List<pb_Tuple<pb_Face, pb_Edge>> GetNeighborFaces(pb_Object pb, pb_Edge edge, Dictionary<int, int> lookup = null)
{
if (lookup == null)
{
lookup = pb.sharedIndices.ToDictionary();
}
List<pb_Tuple<pb_Face, pb_Edge>> list = new List<pb_Tuple<pb_Face, pb_Edge>>();
pb_Edge pb_Edge = new pb_Edge(lookup[edge.x], lookup[edge.y]);
pb_Edge pb_Edge2 = new pb_Edge(0, 0);
for (int i = 0; i < pb.faces.Length; i++)
{
pb_Edge[] edges = pb.faces[i].edges;
for (int j = 0; j < edges.Length; j++)
{
pb_Edge2.x = edges[j].x;
pb_Edge2.y = edges[j].y;
if ((pb_Edge.x == lookup[pb_Edge2.x] && pb_Edge.y == lookup[pb_Edge2.y]) || (pb_Edge.x == lookup[pb_Edge2.y] && pb_Edge.y == lookup[pb_Edge2.x]))
{
list.Add(new pb_Tuple<pb_Face, pb_Edge>(pb.faces[i], new pb_Edge(edges[j])));
break;
}
}
}
return list;
}
// Token: 0x0600001B RID: 27 RVA: 0x00004EF8 File Offset: 0x000032F8
public static pb_Face[] GetNeighborFaces(pb_Object pb, pb_Edge[] edges)
{
List<pb_Face> list = new List<pb_Face>();
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
foreach (pb_Face pb_Face in pb.faces)
{
foreach (pb_Edge pb_Edge in edges)
{
if (pb_Face.edges.IndexOf(pb_Edge, dictionary) > -1)
{
list.Add(pb_Face);
}
}
}
return list.Distinct<pb_Face>().ToArray<pb_Face>();
}
// Token: 0x0600001C RID: 28 RVA: 0x00004F84 File Offset: 0x00003384
internal static List<pb_Face>[][] GetNeighborFacesJagged(pb_Object pb, pb_Edge[][] selEdges)
{
int num = selEdges.Length;
List<pb_Face>[][] array = new List<pb_Face>[num][];
for (int i = 0; i < num; i++)
{
array[i] = new List<pb_Face>[selEdges[i].Length];
for (int j = 0; j < selEdges[i].Length; j++)
{
array[i][j] = new List<pb_Face>();
}
}
pb_IntArray[] sharedIndices = pb.sharedIndices;
pb_Edge[][] array2 = new pb_Edge[num][];
for (int k = 0; k < num; k++)
{
array2[k] = pb_Edge.GetUniversalEdges(selEdges[k], sharedIndices).Distinct<pb_Edge>().ToArray<pb_Edge>();
}
for (int l = 0; l < pb.faces.Length; l++)
{
pb_Edge[] array3 = pb_Edge.GetUniversalEdges(pb.faces[l].edges, sharedIndices).Distinct<pb_Edge>().ToArray<pb_Edge>();
for (int m = 0; m < num; m++)
{
int num2 = -1;
for (int n = 0; n < array2[m].Length; n++)
{
if (array3.Contains(array2[m][n]))
{
num2 = n;
break;
}
}
if (num2 > -1)
{
array[m][num2].Add(pb.faces[l]);
}
}
}
return array;
}
// Token: 0x0600001D RID: 29 RVA: 0x000050CC File Offset: 0x000034CC
public static List<pb_Face> GetNeighborFaces(pb_Object pb, int index)
{
List<pb_Face> list = new List<pb_Face>();
pb_IntArray[] sharedIndices = pb.sharedIndices;
int num = sharedIndices.IndexOf(index);
foreach (pb_Face pb_Face in pb.faces)
{
if (pb_Face.distinctIndices.ContainsMatch(sharedIndices[num]))
{
list.Add(pb_Face);
}
}
return list;
}
// Token: 0x0600001E RID: 30 RVA: 0x00005138 File Offset: 0x00003538
public static IEnumerable<pb_Face> GetNeighborFaces(pb_Object pb, IEnumerable<int> indices)
{
List<pb_Face> list = new List<pb_Face>();
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
HashSet<int> hashSet = new HashSet<int>();
foreach (int num in indices)
{
hashSet.Add(dictionary[num]);
}
for (int i = 0; i < pb.faces.Length; i++)
{
int[] distinctIndices = pb.faces[i].distinctIndices;
for (int j = 0; j < distinctIndices.Length; j++)
{
if (hashSet.Contains(dictionary[distinctIndices[j]]))
{
list.Add(pb.faces[i]);
break;
}
}
}
return list;
}
// Token: 0x0600001F RID: 31 RVA: 0x00005224 File Offset: 0x00003624
public static pb_Edge[] GetConnectedEdges(pb_Object pb, int[] indices)
{
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
List<pb_Edge> list = new List<pb_Edge>();
HashSet<int> hashSet = new HashSet<int>();
for (int i = 0; i < indices.Length; i++)
{
hashSet.Add(dictionary[indices[i]]);
}
pb_Edge[] array = pb_Edge.AllEdges(pb.faces);
HashSet<pb_Edge> hashSet2 = new HashSet<pb_Edge>();
pb_Edge pb_Edge = new pb_Edge(0, 0);
for (int j = 0; j < array.Length; j++)
{
pb_Edge pb_Edge2 = new pb_Edge(dictionary[array[j].x], dictionary[array[j].y]);
if (hashSet.Contains(pb_Edge2.x) || (hashSet.Contains(pb_Edge2.y) && !hashSet2.Contains(pb_Edge)))
{
list.Add(array[j]);
hashSet2.Add(pb_Edge2);
}
}
return list.ToArray();
}
// Token: 0x06000020 RID: 32 RVA: 0x00005317 File Offset: 0x00003717
public static IEnumerable<pb_Edge> GetPerimeterEdges(pb_Object pb, IEnumerable<pb_Face> faces)
{
return pbMeshUtils.GetPerimeterEdges(pb.sharedIndices.ToDictionary(), faces);
}
// Token: 0x06000021 RID: 33 RVA: 0x0000532C File Offset: 0x0000372C
public static IEnumerable<pb_Edge> GetPerimeterEdges(Dictionary<int, int> sharedIndicesLookup, IEnumerable<pb_Face> faces)
{
List<pb_Edge> list = faces.SelectMany((pb_Face x) => x.edges).ToList<pb_Edge>();
int count = list.Count;
Dictionary<pb_Edge, List<pb_Edge>> dictionary = new Dictionary<pb_Edge, List<pb_Edge>>();
for (int i = 0; i < count; i++)
{
pb_Edge pb_Edge = new pb_Edge(sharedIndicesLookup[list[i].x], sharedIndicesLookup[list[i].y]);
List<pb_Edge> list2;
if (dictionary.TryGetValue(pb_Edge, out list2))
{
list2.Add(list[i]);
}
else
{
dictionary.Add(pb_Edge, new List<pb_Edge> { list[i] });
}
}
return from x in dictionary
where x.Value.Count < 2
select x.Value[0];
}
// Token: 0x06000022 RID: 34 RVA: 0x0000543C File Offset: 0x0000383C
public static int[] GetPerimeterEdges(pb_Object pb, pb_Edge[] edges)
{
if (edges.Length == pb_Edge.AllEdges(pb.faces).Length || edges.Length < 3)
{
return new int[0];
}
pb_Edge[] universalEdges = pb_Edge.GetUniversalEdges(edges, pb.sharedIndices.ToDictionary());
int[] array = new int[universalEdges.Length];
for (int i = 0; i < universalEdges.Length - 1; i++)
{
for (int j = i + 1; j < universalEdges.Length; j++)
{
if (universalEdges[i].x == universalEdges[j].x || universalEdges[i].x == universalEdges[j].y || universalEdges[i].y == universalEdges[j].x || universalEdges[i].y == universalEdges[j].y)
{
array[i]++;
array[j]++;
}
}
}
int num = pb_Math.Min<int>(array);
List<int> list = new List<int>();
for (int k = 0; k < array.Length; k++)
{
if (array[k] <= num)
{
list.Add(k);
}
}
return (list.Count == edges.Length) ? new int[0] : list.ToArray();
}
// Token: 0x06000023 RID: 35 RVA: 0x00005580 File Offset: 0x00003980
public static IEnumerable<pb_Face> GetPerimeterFaces(pb_Object pb, IEnumerable<pb_Face> faces)
{
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
Dictionary<pb_Edge, List<pb_Face>> dictionary2 = new Dictionary<pb_Edge, List<pb_Face>>();
foreach (pb_Face pb_Face in faces)
{
foreach (pb_Edge pb_Edge in pb_Face.edges)
{
pb_Edge pb_Edge2 = new pb_Edge(dictionary[pb_Edge.x], dictionary[pb_Edge.y]);
if (dictionary2.ContainsKey(pb_Edge2))
{
dictionary2[pb_Edge2].Add(pb_Face);
}
else
{
dictionary2.Add(pb_Edge2, new List<pb_Face> { pb_Face });
}
}
}
return (from x in dictionary2
where x.Value.Count < 2
select x.Value[0]).Distinct<pb_Face>();
}
// Token: 0x06000024 RID: 36 RVA: 0x000056AC File Offset: 0x00003AAC
public static int[] GetPerimeterVertices(pb_Object pb, int[] indices, pb_Edge[] universal_edges_all)
{
int num = indices.Length;
pb_IntArray[] sharedIndices = pb.sharedIndices;
int[] array = new int[num];
for (int i = 0; i < num; i++)
{
array[i] = sharedIndices.IndexOf(indices[i]);
}
int[] array2 = new int[indices.Length];
for (int j = 0; j < indices.Length - 1; j++)
{
for (int k = j + 1; k < indices.Length; k++)
{
if (universal_edges_all.Contains(array[j], array[k]))
{
array2[j]++;
array2[k]++;
}
}
}
int num2 = pb_Math.Min<int>(array2);
List<int> list = new List<int>();
for (int l = 0; l < num; l++)
{
if (array2[l] <= num2)
{
list.Add(l);
}
}
return (list.Count >= num) ? new int[0] : list.ToArray();
}
// Token: 0x06000025 RID: 37 RVA: 0x000057B4 File Offset: 0x00003BB4
private static pb_WingedEdge EdgeRingNext(pb_WingedEdge edge)
{
if (edge == null)
{
return null;
}
pb_WingedEdge pb_WingedEdge = edge.next;
pb_WingedEdge pb_WingedEdge2 = edge.previous;
int num = 0;
while (pb_WingedEdge != pb_WingedEdge2 && pb_WingedEdge != edge)
{
pb_WingedEdge = pb_WingedEdge.next;
if (pb_WingedEdge == pb_WingedEdge2)
{
return null;
}
pb_WingedEdge2 = pb_WingedEdge2.previous;
num++;
}
if (num % 2 == 0 || pb_WingedEdge == edge)
{
pb_WingedEdge = null;
}
return pb_WingedEdge;
}
// Token: 0x06000026 RID: 38 RVA: 0x0000581C File Offset: 0x00003C1C
public static IEnumerable<pb_Edge> GetEdgeRing(pb_Object pb, pb_Edge[] edges)
{
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, false);
List<pb_EdgeLookup> list = pb_EdgeLookup.GetEdgeLookup(edges, pb.sharedIndices.ToDictionary()).ToList<pb_EdgeLookup>();
list.Distinct<pb_EdgeLookup>();
Dictionary<pb_Edge, pb_WingedEdge> dictionary = new Dictionary<pb_Edge, pb_WingedEdge>();
for (int i = 0; i < wingedEdges.Count; i++)
{
if (!dictionary.ContainsKey(wingedEdges[i].edge.common))
{
dictionary.Add(wingedEdges[i].edge.common, wingedEdges[i]);
}
}
HashSet<pb_EdgeLookup> hashSet = new HashSet<pb_EdgeLookup>();
for (int j = 0; j < list.Count; j++)
{
pb_WingedEdge pb_WingedEdge;
if (dictionary.TryGetValue(list[j].common, out pb_WingedEdge) && !hashSet.Contains(pb_WingedEdge.edge))
{
pb_WingedEdge pb_WingedEdge2 = pb_WingedEdge;
while (pb_WingedEdge2 != null)
{
if (!hashSet.Add(pb_WingedEdge2.edge))
{
break;
}
pb_WingedEdge2 = pbMeshUtils.EdgeRingNext(pb_WingedEdge2);
if (pb_WingedEdge2 != null && pb_WingedEdge2.opposite != null)
{
pb_WingedEdge2 = pb_WingedEdge2.opposite;
}
}
pb_WingedEdge2 = pbMeshUtils.EdgeRingNext(pb_WingedEdge.opposite);
if (pb_WingedEdge2 != null && pb_WingedEdge2.opposite != null)
{
pb_WingedEdge2 = pb_WingedEdge2.opposite;
}
while (pb_WingedEdge2 != null)
{
if (!hashSet.Add(pb_WingedEdge2.edge))
{
break;
}
pb_WingedEdge2 = pbMeshUtils.EdgeRingNext(pb_WingedEdge2);
if (pb_WingedEdge2 != null && pb_WingedEdge2.opposite != null)
{
pb_WingedEdge2 = pb_WingedEdge2.opposite;
}
}
}
}
return hashSet.Select((pb_EdgeLookup x) => x.local);
}
// Token: 0x06000027 RID: 39 RVA: 0x000059E0 File Offset: 0x00003DE0
public static bool GetEdgeLoop(pb_Object pb, pb_Edge[] edges, out pb_Edge[] loop)
{
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, false);
IEnumerable<pb_EdgeLookup> edgeLookup = pb_EdgeLookup.GetEdgeLookup(edges, pb.sharedIndices.ToDictionary());
HashSet<pb_EdgeLookup> hashSet = new HashSet<pb_EdgeLookup>(edgeLookup);
HashSet<pb_EdgeLookup> hashSet2 = new HashSet<pb_EdgeLookup>();
for (int i = 0; i < wingedEdges.Count; i++)
{
if (!hashSet2.Contains(wingedEdges[i].edge) && hashSet.Contains(wingedEdges[i].edge))
{
if (!pbMeshUtils.GetEdgeLoopInternal(wingedEdges[i], wingedEdges[i].edge.common.y, hashSet2))
{
pbMeshUtils.GetEdgeLoopInternal(wingedEdges[i], wingedEdges[i].edge.common.x, hashSet2);
}
}
}
loop = hashSet2.Select((pb_EdgeLookup x) => x.local).ToArray<pb_Edge>();
return true;
}
// Token: 0x06000028 RID: 40 RVA: 0x00005AE4 File Offset: 0x00003EE4
private static bool GetEdgeLoopInternal(pb_WingedEdge start, int startIndex, HashSet<pb_EdgeLookup> used)
{
int num = startIndex;
pb_WingedEdge pb_WingedEdge = start;
do
{
used.Add(pb_WingedEdge.edge);
List<pb_WingedEdge> list = pbMeshUtils.GetSpokes(pb_WingedEdge, num, true).DistinctBy((pb_WingedEdge x) => x.edge.common).ToList<pb_WingedEdge>();
pb_WingedEdge = null;
if (list != null && list.Count == 4)
{
pb_WingedEdge = list[2];
num = ((pb_WingedEdge.edge.common.x != num) ? pb_WingedEdge.edge.common.x : pb_WingedEdge.edge.common.y);
}
}
while (pb_WingedEdge != null && !used.Contains(pb_WingedEdge.edge));
return pb_WingedEdge != null;
}
// Token: 0x06000029 RID: 41 RVA: 0x00005BA8 File Offset: 0x00003FA8
private static pb_WingedEdge NextSpoke(pb_WingedEdge wing, int pivot, bool opp)
{
if (opp)
{
return wing.opposite;
}
if (wing.next.edge.common.Contains(pivot))
{
return wing.next;
}
if (wing.previous.edge.common.Contains(pivot))
{
return wing.previous;
}
return null;
}
// Token: 0x0600002A RID: 42 RVA: 0x00005C08 File Offset: 0x00004008
public static List<pb_WingedEdge> GetSpokes(pb_WingedEdge wing, int sharedIndex, bool allowHoles = false)
{
List<pb_WingedEdge> list = new List<pb_WingedEdge>();
pb_WingedEdge pb_WingedEdge = wing;
bool flag = false;
for (;;)
{
list.Add(pb_WingedEdge);
pb_WingedEdge = pbMeshUtils.NextSpoke(pb_WingedEdge, sharedIndex, flag);
flag = !flag;
if (pb_WingedEdge != null && pb_WingedEdge.edge.common.Equals(wing.edge.common))
{
break;
}
if (pb_WingedEdge == null)
{
goto Block_3;
}
}
return list;
Block_3:
if (!allowHoles)
{
return null;
}
pb_WingedEdge = wing.opposite;
flag = false;
List<pb_WingedEdge> list2 = new List<pb_WingedEdge>();
while (pb_WingedEdge != null && !pb_WingedEdge.edge.common.Equals(wing.edge.common))
{
list2.Add(pb_WingedEdge);
pb_WingedEdge = pbMeshUtils.NextSpoke(pb_WingedEdge, sharedIndex, flag);
flag = !flag;
}
list2.Reverse();
list.AddRange(list2);
return list;
}
}
}
@@ -0,0 +1,209 @@
using System;
using System.Collections.Generic;
using ProBuilder2.Common;
using UnityEngine;
namespace ProBuilder2.MeshOperations
{
// Token: 0x02000004 RID: 4
public static class pbTriangleOps
{
// Token: 0x06000033 RID: 51 RVA: 0x00005D2C File Offset: 0x0000412C
public static void ReverseWindingOrder(this pb_Object pb, pb_Face[] faces)
{
for (int i = 0; i < faces.Length; i++)
{
faces[i].ReverseIndices();
}
}
// Token: 0x06000034 RID: 52 RVA: 0x00005D58 File Offset: 0x00004158
public static WindingOrder GetWindingOrder(this pb_Object pb, pb_Face face)
{
Vector2[] array = pb_Projection.PlanarProject(pb, face);
return pbTriangleOps.GetWindingOrder(array);
}
// Token: 0x06000035 RID: 53 RVA: 0x00005D74 File Offset: 0x00004174
public static WindingOrder GetWindingOrder(IList<pb_Vertex> vertices, IList<int> indices)
{
Vector2[] array = pb_Projection.PlanarProject(vertices, indices);
return pbTriangleOps.GetWindingOrder(array);
}
// Token: 0x06000036 RID: 54 RVA: 0x00005D90 File Offset: 0x00004190
public static WindingOrder GetWindingOrder(IList<Vector2> points)
{
float num = 0f;
int count = points.Count;
for (int i = 0; i < count; i++)
{
Vector2 vector = points[i];
Vector2 vector2 = ((i >= count - 1) ? points[0] : points[i + 1]);
num += (vector2.x - vector.x) * (vector2.y + vector.y);
}
return (num != 0f) ? ((num <= 0f) ? WindingOrder.CounterClockwise : WindingOrder.Clockwise) : WindingOrder.Unknown;
}
// Token: 0x06000037 RID: 55 RVA: 0x00005E2C File Offset: 0x0000422C
public static bool FlipEdge(this pb_Object pb, pb_Face face)
{
int[] indices = face.indices;
if (indices.Length != 6)
{
return false;
}
int[] array = pbUtil.FilledArray<int>(1, indices.Length);
for (int i = 0; i < indices.Length - 1; i++)
{
for (int j = i + 1; j < indices.Length; j++)
{
if (indices[i] == indices[j])
{
array[i]++;
array[j]++;
}
}
}
if (array[0] + array[1] + array[2] != 5 || array[3] + array[4] + array[5] != 5)
{
return false;
}
int num = indices[(array[0] != 1) ? ((array[1] != 1) ? 2 : 1) : 0];
int num2 = indices[(array[3] != 1) ? ((array[4] != 1) ? 5 : 4) : 3];
int num3 = -1;
if (array[0] == 2)
{
num3 = indices[0];
indices[0] = num2;
}
else if (array[1] == 2)
{
num3 = indices[1];
indices[1] = num2;
}
else if (array[2] == 2)
{
num3 = indices[2];
indices[2] = num2;
}
if (array[3] == 2 && indices[3] != num3)
{
indices[3] = num;
}
else if (array[4] == 2 && indices[4] != num3)
{
indices[4] = num;
}
else if (array[5] == 2 && indices[5] != num3)
{
indices[5] = num;
}
return true;
}
// Token: 0x06000038 RID: 56 RVA: 0x00005FA8 File Offset: 0x000043A8
public static bool RemoveDegenerateTriangles(this pb_Object pb, out int[] removed)
{
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
Dictionary<int, int> dictionary2 = ((pb.sharedIndicesUV == null) ? new Dictionary<int, int>() : pb.sharedIndicesUV.ToDictionary());
Vector3[] vertices = pb.vertices;
Dictionary<int, int> dictionary3 = new Dictionary<int, int>();
Dictionary<int, int> dictionary4 = new Dictionary<int, int>();
List<pb_Face> list = new List<pb_Face>();
foreach (pb_Face pb_Face in pb.faces)
{
List<int> list2 = new List<int>();
int[] indices = pb_Face.indices;
for (int j = 0; j < indices.Length; j += 3)
{
float num = pb_Math.TriangleArea(vertices[indices[j]], vertices[indices[j + 1]], vertices[indices[j + 2]]);
if (num > Mathf.Epsilon)
{
int num2 = dictionary[indices[j]];
int num3 = dictionary[indices[j + 1]];
int num4 = dictionary[indices[j + 2]];
if (num2 != num3 && num2 != num4 && num3 != num4)
{
list2.Add(indices[j]);
list2.Add(indices[j + 1]);
list2.Add(indices[j + 2]);
if (!dictionary3.ContainsKey(indices[j]))
{
dictionary3.Add(indices[j], num2);
}
if (!dictionary3.ContainsKey(indices[j + 1]))
{
dictionary3.Add(indices[j + 1], num3);
}
if (!dictionary3.ContainsKey(indices[j + 2]))
{
dictionary3.Add(indices[j + 2], num4);
}
if (dictionary2.ContainsKey(indices[j]) && !dictionary4.ContainsKey(indices[j]))
{
dictionary4.Add(indices[j], dictionary2[indices[j]]);
}
if (dictionary2.ContainsKey(indices[j + 1]) && !dictionary4.ContainsKey(indices[j + 1]))
{
dictionary4.Add(indices[j + 1], dictionary2[indices[j + 1]]);
}
if (dictionary2.ContainsKey(indices[j + 2]) && !dictionary4.ContainsKey(indices[j + 2]))
{
dictionary4.Add(indices[j + 2], dictionary2[indices[j + 2]]);
}
}
}
}
if (list2.Count > 0)
{
pb_Face.SetIndices(list2.ToArray());
pb_Face.RebuildCaches();
list.Add(pb_Face);
}
}
pb.SetFaces(list.ToArray());
pb.SetSharedIndices(dictionary3);
pb.SetSharedIndicesUV(dictionary4);
removed = pb.RemoveUnusedVertices();
return removed.Length > 0;
}
// Token: 0x06000039 RID: 57 RVA: 0x00006270 File Offset: 0x00004670
public static pb_Face MergeFaces(this pb_Object pb, pb_Face[] faces)
{
List<int> list = new List<int>(faces[0].indices);
for (int i = 1; i < faces.Length; i++)
{
list.AddRange(faces[i].indices);
}
pb_Face pb_Face = new pb_Face(list.ToArray(), faces[0].material, faces[0].uv, faces[0].smoothingGroup, faces[0].textureGroup, faces[0].elementGroup, faces[0].manualUV);
pb_Face[] array = new pb_Face[pb.faces.Length - faces.Length + 1];
int num = 0;
foreach (pb_Face pb_Face2 in pb.faces)
{
if (Array.IndexOf<pb_Face>(faces, pb_Face2) < 0)
{
array[num++] = pb_Face2;
}
}
array[num] = pb_Face;
pb.SetFaces(array);
Dictionary<int, int> dictionary = new Dictionary<int, int>();
for (int k = 0; k < pb_Face.indices.Length; k++)
{
int num2 = pb.sharedIndices.IndexOf(pb_Face.indices[k]);
if (dictionary.ContainsKey(num2))
{
pb_Face.indices[k] = dictionary[num2];
}
else
{
dictionary.Add(num2, pb_Face.indices[k]);
}
}
pb.RemoveUnusedVertices();
return pb_Face;
}
}
}
@@ -0,0 +1,372 @@
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;
}
}
}
@@ -0,0 +1,387 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ProBuilder2.Common;
using UnityEngine;
namespace ProBuilder2.MeshOperations
{
// Token: 0x02000006 RID: 6
public static class pbVertexOps
{
// Token: 0x06000047 RID: 71 RVA: 0x00007250 File Offset: 0x00005650
public static bool MergeVertices(this pb_Object pb, int[] indices, out int collapsedIndex, bool collapseToFirst = false)
{
pb_Vertex[] vertices = pb_Vertex.GetVertices(pb, null);
pb_Vertex pb_Vertex = ((!collapseToFirst) ? pb_Vertex.Average(vertices, indices) : vertices[indices[0]]);
pb_IntArray[] sharedIndices = pb.sharedIndices;
pb_IntArray[] sharedIndicesUV = pb.sharedIndicesUV;
int num = pb_IntArrayUtility.MergeSharedIndices(ref sharedIndices, indices);
pb_IntArrayUtility.MergeSharedIndices(ref sharedIndicesUV, indices);
pb.SetSharedIndices(sharedIndices);
pb.SetSharedIndicesUV(sharedIndicesUV);
pb.SetSharedVertexValues(num, pb_Vertex);
int[] array = pb.GetSharedIndices()[num].array;
int[] array2;
pb.RemoveDegenerateTriangles(out array2);
int num2 = -1;
for (int i = 0; i < array.Length; i++)
{
if (!array2.Contains(array[i]))
{
num2 = array[i];
}
}
int num3 = num2;
for (int j = 0; j < array2.Length; j++)
{
if (num2 > array2[j])
{
num3--;
}
}
if (num3 > -1)
{
collapsedIndex = num3;
return true;
}
collapsedIndex = -1;
return false;
}
// Token: 0x06000048 RID: 72 RVA: 0x00007344 File Offset: 0x00005744
public static bool SplitCommonVertices(this pb_Object pb, int[] indices)
{
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
pb_IntArray[] sharedIndices = pb.sharedIndices;
List<int> list = new List<int>();
List<int> list2 = new List<int>();
for (int i = 0; i < indices.Length; i++)
{
int num = dictionary[indices[i]];
if (!list.Contains(num))
{
list.Add(num);
list2.AddRange(sharedIndices[num].array);
}
}
pb_IntArrayUtility.RemoveValues(ref sharedIndices, list2.ToArray());
foreach (int num2 in list2)
{
pb_IntArrayUtility.AddValueAtIndex(ref sharedIndices, -1, num2);
}
pb.SetSharedIndices(sharedIndices);
return true;
}
// Token: 0x06000049 RID: 73 RVA: 0x00007420 File Offset: 0x00005820
public static void SplitVertices(this pb_Object pb, pb_Edge edge)
{
pb.SplitVertices(new int[] { edge.x, edge.y });
}
// Token: 0x0600004A RID: 74 RVA: 0x00007440 File Offset: 0x00005840
public static void SplitVertices(this pb_Object pb, IEnumerable<int> indices)
{
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
int num = dictionary.Count<KeyValuePair<int, int>>();
foreach (int num2 in indices)
{
num = (dictionary[num2] = num + 1);
}
pb.SetSharedIndices(dictionary);
}
// Token: 0x0600004B RID: 75 RVA: 0x000074B4 File Offset: 0x000058B4
public static bool AppendVerticesToFace(this pb_Object pb, pb_Face face, Vector3[] points, Color[] addColors, out pb_Face newFace)
{
if (!face.IsValid())
{
newFace = face;
return false;
}
List<pb_Vertex> list = pb_Vertex.GetVertices(pb, null).ToList<pb_Vertex>();
List<pb_Face> list2 = new List<pb_Face>(pb.faces);
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
Dictionary<int, int> dictionary2 = ((pb.sharedIndicesUV != null) ? pb.sharedIndicesUV.ToDictionary() : null);
List<pb_Edge> list3 = pb_WingedEdge.SortEdgesByAdjacency(face);
List<pb_Vertex> list4 = new List<pb_Vertex>();
List<int> list5 = new List<int>();
List<int> list6 = ((dictionary2 == null) ? null : new List<int>());
for (int i = 0; i < list3.Count; i++)
{
list4.Add(list[list3[i].x]);
list5.Add(dictionary[list3[i].x]);
if (dictionary2 != null)
{
int num;
if (dictionary2.TryGetValue(list3[i].x, out num))
{
list6.Add(num);
}
else
{
list6.Add(-1);
}
}
}
for (int j = 0; j < points.Length; j++)
{
int num2 = -1;
float num3 = float.PositiveInfinity;
Vector3 vector = points[j];
int count = list4.Count;
for (int k = 0; k < count; k++)
{
Vector3 position = list4[k].position;
Vector3 position2 = list4[(k + 1) % count].position;
float num4 = pb_Math.DistancePointLineSegment(vector, position, position2);
if (num4 < num3)
{
num3 = num4;
num2 = k;
}
}
pb_Vertex pb_Vertex = list4[num2];
pb_Vertex pb_Vertex2 = list4[(num2 + 1) % count];
float sqrMagnitude = (vector - pb_Vertex.position).sqrMagnitude;
float sqrMagnitude2 = (vector - pb_Vertex2.position).sqrMagnitude;
pb_Vertex pb_Vertex3 = pb_Vertex.Mix(pb_Vertex, pb_Vertex2, sqrMagnitude / (sqrMagnitude + sqrMagnitude2));
list4.Insert((num2 + 1) % count, pb_Vertex3);
list5.Insert((num2 + 1) % count, -1);
if (list6 != null)
{
list6.Insert((num2 + 1) % count, -1);
}
}
List<int> list7;
try
{
pb_Triangulation.TriangulateVertices(list4, out list7, false, false);
}
catch
{
Debug.Log("Failed triangulating face after appending vertices.");
newFace = null;
return false;
}
pb_FaceRebuildData pb_FaceRebuildData = new pb_FaceRebuildData();
pb_FaceRebuildData.face = new pb_Face(list7.ToArray(), face.material, new pb_UV(face.uv), face.smoothingGroup, face.textureGroup, -1, face.manualUV);
pb_FaceRebuildData.vertices = list4;
pb_FaceRebuildData.sharedIndices = list5;
pb_FaceRebuildData.sharedIndicesUV = list6;
pb_FaceRebuildData.Apply(new List<pb_FaceRebuildData> { pb_FaceRebuildData }, list, list2, dictionary, dictionary2);
newFace = pb_FaceRebuildData.face;
pb.SetVertices(list, false);
pb.SetFaces(list2.ToArray());
pb.SetSharedIndices(dictionary);
pb.SetSharedIndicesUV(dictionary2);
Vector3 vector2 = pb_Math.Normal(pb, face);
Vector3 vector3 = pb_Math.Normal(pb, newFace);
if (Vector3.Dot(vector2, vector3) < 0f)
{
newFace.ReverseIndices();
}
pb.DeleteFace(face);
return true;
}
// Token: 0x0600004C RID: 76 RVA: 0x00007804 File Offset: 0x00005C04
public static pb_ActionResult AppendVerticesToEdge(this pb_Object pb, pb_Edge edge, int count, out List<pb_Edge> newEdges)
{
return pb.AppendVerticesToEdge(new pb_Edge[] { edge }, count, out newEdges);
}
// Token: 0x0600004D RID: 77 RVA: 0x00007818 File Offset: 0x00005C18
public static pb_ActionResult AppendVerticesToEdge(this pb_Object pb, IList<pb_Edge> edges, int count, out List<pb_Edge> newEdges)
{
newEdges = new List<pb_Edge>();
if (count < 1 || count > 512)
{
return new pb_ActionResult(Status.Failure, "New edge vertex count is less than 1 or greater than 512.");
}
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
Dictionary<int, int> dictionary2 = pb.sharedIndicesUV.ToDictionary();
List<int> list2 = new List<int>();
pb_Edge[] universalEdges = pb_Edge.GetUniversalEdges(edges.ToArray<pb_Edge>(), dictionary);
List<pb_Edge> list3 = universalEdges.Distinct<pb_Edge>().ToList<pb_Edge>();
Dictionary<pb_Face, pb_FaceRebuildData> dictionary3 = new Dictionary<pb_Face, pb_FaceRebuildData>();
int num = dictionary.Count<KeyValuePair<int, int>>();
int num2 = num;
foreach (pb_Edge pb_Edge in list3)
{
pb_Edge localEdgeFast = pb_Edge.GetLocalEdgeFast(pb_Edge, pb.sharedIndices);
List<pb_Vertex> list4 = new List<pb_Vertex>(count);
for (int i = 0; i < count; i++)
{
list4.Add(pb_Vertex.Mix(list[localEdgeFast.x], list[localEdgeFast.y], (float)(i + 1) / ((float)count + 1f)));
}
List<pb_Tuple<pb_Face, pb_Edge>> neighborFaces = pbMeshUtils.GetNeighborFaces(pb, localEdgeFast, null);
foreach (pb_Tuple<pb_Face, pb_Edge> pb_Tuple in neighborFaces)
{
pb_Face item = pb_Tuple.Item1;
pb_FaceRebuildData pb_FaceRebuildData;
if (!dictionary3.TryGetValue(item, out pb_FaceRebuildData))
{
pb_FaceRebuildData = new pb_FaceRebuildData();
pb_FaceRebuildData.face = new pb_Face(null, item.material, new pb_UV(item.uv), item.smoothingGroup, item.textureGroup, -1, item.manualUV);
pb_FaceRebuildData.vertices = new List<pb_Vertex>(list.ValuesWithIndices(item.distinctIndices));
pb_FaceRebuildData.sharedIndices = new List<int>();
pb_FaceRebuildData.sharedIndicesUV = new List<int>();
foreach (int num3 in item.distinctIndices)
{
int num4;
if (dictionary.TryGetValue(num3, out num4))
{
pb_FaceRebuildData.sharedIndices.Add(num4);
}
if (dictionary2.TryGetValue(num3, out num4))
{
pb_FaceRebuildData.sharedIndicesUV.Add(num4);
}
}
list2.AddRange(item.distinctIndices);
dictionary3.Add(item, pb_FaceRebuildData);
}
pb_FaceRebuildData.vertices.AddRange(list4);
for (int k = 0; k < count; k++)
{
pb_FaceRebuildData.sharedIndices.Add(num2 + k);
pb_FaceRebuildData.sharedIndicesUV.Add(-1);
}
}
num2 += count;
}
List<pb_Face> list5 = dictionary3.Keys.ToList<pb_Face>();
List<pb_FaceRebuildData> list6 = dictionary3.Values.ToList<pb_FaceRebuildData>();
List<pb_EdgeLookup> list7 = new List<pb_EdgeLookup>();
for (int l = 0; l < list5.Count; l++)
{
pb_Face pb_Face = list5[l];
pb_FaceRebuildData pb_FaceRebuildData2 = list6[l];
Vector3 vector = pb_Math.Normal(pb, pb_Face);
Vector2[] array = pb_Projection.PlanarProject(pb_FaceRebuildData2.vertices.Select((pb_Vertex x) => x.position).ToArray<Vector3>(), vector);
int count2 = list.Count;
List<int> list8;
if (pb_Triangulation.SortAndTriangulate(array, out list8, false))
{
pb_FaceRebuildData2.face.SetIndices(list8.ToArray());
pb_FaceRebuildData2.face.ShiftIndices(count2);
pb_Face.CopyFrom(pb_FaceRebuildData2.face);
for (int m = 0; m < pb_FaceRebuildData2.vertices.Count; m++)
{
dictionary.Add(count2 + m, pb_FaceRebuildData2.sharedIndices[m]);
}
if (pb_FaceRebuildData2.sharedIndicesUV.Count == pb_FaceRebuildData2.vertices.Count)
{
for (int n = 0; n < pb_FaceRebuildData2.vertices.Count; n++)
{
dictionary2.Add(count2 + n, pb_FaceRebuildData2.sharedIndicesUV[n]);
}
}
list.AddRange(pb_FaceRebuildData2.vertices);
foreach (pb_Edge pb_Edge2 in pb_Face.edges)
{
pb_EdgeLookup pb_EdgeLookup = new pb_EdgeLookup(new pb_Edge(dictionary[pb_Edge2.x], dictionary[pb_Edge2.y]), pb_Edge2);
if (pb_EdgeLookup.common.x >= num || pb_EdgeLookup.common.y >= num)
{
list7.Add(pb_EdgeLookup);
}
}
}
}
list2 = list2.Distinct<int>().ToList<int>();
int delCount = list2.Count;
newEdges = (from x in list7.Distinct<pb_EdgeLookup>()
select x.local - delCount).ToList<pb_Edge>();
pb.SetVertices(list, false);
pb.SetSharedIndices(dictionary.ToSharedIndices());
pb.SetSharedIndicesUV(dictionary2.ToSharedIndices());
pb.DeleteVerticesWithIndices(list2);
return new pb_ActionResult(Status.Success, "Subdivide Edges");
}
// Token: 0x0600004E RID: 78 RVA: 0x00007D74 File Offset: 0x00006174
public static pb_FaceRebuildData ExplodeVertex(IList<pb_Vertex> vertices, IList<pb_Tuple<pb_WingedEdge, int>> edgeAndCommonIndex, float distance, out Dictionary<int, List<int>> appendedVertices)
{
pb_Face face = edgeAndCommonIndex.FirstOrDefault<pb_Tuple<pb_WingedEdge, int>>().Item1.face;
List<pb_Edge> list = pb_WingedEdge.SortEdgesByAdjacency(face);
appendedVertices = new Dictionary<int, List<int>>();
Vector3 vector = pb_Math.Normal(vertices, face.indices);
Dictionary<int, int> dictionary = new Dictionary<int, int>();
foreach (pb_Tuple<pb_WingedEdge, int> pb_Tuple in edgeAndCommonIndex)
{
if (pb_Tuple.Item2 == pb_Tuple.Item1.edge.common.x)
{
dictionary.Add(pb_Tuple.Item1.edge.local.x, pb_Tuple.Item2);
}
else
{
dictionary.Add(pb_Tuple.Item1.edge.local.y, pb_Tuple.Item2);
}
}
int count = list.Count;
List<pb_Vertex> list2 = new List<pb_Vertex>();
for (int i = 0; i < count; i++)
{
int y = list[i].y;
if (dictionary.ContainsKey(y))
{
pb_Vertex pb_Vertex = vertices[list[i].x];
pb_Vertex pb_Vertex2 = vertices[list[i].y];
pb_Vertex pb_Vertex3 = vertices[list[(i + 1) % count].y];
pb_Vertex pb_Vertex4 = pb_Vertex - pb_Vertex2;
pb_Vertex pb_Vertex5 = pb_Vertex3 - pb_Vertex2;
pb_Vertex4.Normalize();
pb_Vertex5.Normalize();
pb_Vertex pb_Vertex6 = vertices[y] + pb_Vertex4 * distance;
pb_Vertex pb_Vertex7 = vertices[y] + pb_Vertex5 * distance;
appendedVertices.AddOrAppend(dictionary[y], list2.Count);
list2.Add(pb_Vertex6);
appendedVertices.AddOrAppend(dictionary[y], list2.Count);
list2.Add(pb_Vertex7);
}
else
{
list2.Add(vertices[y]);
}
}
List<int> list3;
if (pb_Triangulation.TriangulateVertices(list2, out list3, false, false))
{
pb_FaceRebuildData pb_FaceRebuildData = new pb_FaceRebuildData();
pb_FaceRebuildData.vertices = list2;
pb_FaceRebuildData.face = new pb_Face(face);
Vector3 vector2 = pb_Math.Normal(list2, list3);
if (Vector3.Dot(vector, vector2) < 0f)
{
list3.Reverse();
}
pb_FaceRebuildData.face.SetIndices(list3.ToArray());
return pb_FaceRebuildData;
}
return null;
}
// Token: 0x0600004F RID: 79 RVA: 0x00007FF8 File Offset: 0x000063F8
private static pb_Edge AlignEdgeWithDirection(pb_EdgeLookup edge, int commonIndex)
{
if (edge.common.x == commonIndex)
{
return new pb_Edge(edge.local.x, edge.local.y);
}
return new pb_Edge(edge.local.y, edge.local.x);
}
// Token: 0x06000050 RID: 80 RVA: 0x00008050 File Offset: 0x00006450
public static void Quantize(pb_Object pb, IList<int> indices, Vector3 snap)
{
Vector3[] vertices = pb.vertices;
for (int i = 0; i < indices.Count; i++)
{
vertices[indices[i]] = pb.transform.InverseTransformPoint(pb_Snap.SnapValue(pb.transform.TransformPoint(vertices[indices[i]]), snap));
}
}
}
}
@@ -0,0 +1,188 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ProBuilder2.Common;
using UnityEngine;
namespace ProBuilder2.MeshOperations
{
// Token: 0x02000007 RID: 7
public static class pb_AppendDelete
{
// Token: 0x06000052 RID: 82 RVA: 0x000080E0 File Offset: 0x000064E0
public static pb_Face AppendFace(this pb_Object pb, Vector3[] v, Color[] c, Vector2[] u, pb_Face face)
{
int[] array = new int[v.Length];
for (int i = 0; i < v.Length; i++)
{
array[i] = -1;
}
return pb.AppendFace(v, c, u, face, array);
}
// Token: 0x06000053 RID: 83 RVA: 0x0000811C File Offset: 0x0000651C
public static pb_Face AppendFace(this pb_Object pb, Vector3[] v, Color[] c, Vector2[] u, pb_Face face, int[] sharedIndex)
{
int vertexCount = pb.vertexCount;
Vector3[] array = new Vector3[vertexCount + v.Length];
Color[] array2 = new Color[vertexCount + c.Length];
Vector2[] array3 = new Vector2[pb.uv.Length + u.Length];
List<pb_Face> list = new List<pb_Face>(pb.faces);
pb_IntArray[] sharedIndices = pb.sharedIndices;
Array.Copy(pb.vertices, 0, array, 0, vertexCount);
Array.Copy(v, 0, array, vertexCount, v.Length);
Array.Copy(pb.colors, 0, array2, 0, vertexCount);
Array.Copy(c, 0, array2, vertexCount, c.Length);
Array.Copy(pb.uv, 0, array3, 0, pb.uv.Length);
Array.Copy(u, 0, array3, pb.uv.Length, u.Length);
face.ShiftIndicesToZero();
face.ShiftIndices(vertexCount);
face.RebuildCaches();
list.Add(face);
for (int i = 0; i < sharedIndex.Length; i++)
{
pb_IntArrayUtility.AddValueAtIndex(ref sharedIndices, sharedIndex[i], i + vertexCount);
}
pb.SetVertices(array);
pb.SetColors(array2);
pb.SetUV(array3);
pb.SetSharedIndices(sharedIndices);
pb.SetFaces(list.ToArray());
return face;
}
// Token: 0x06000054 RID: 84 RVA: 0x00008244 File Offset: 0x00006644
public static pb_Face[] AppendFaces(this pb_Object pb, Vector3[][] new_Vertices, Color[][] new_Colors, Vector2[][] new_uvs, pb_Face[] new_Faces, int[][] new_SharedIndices)
{
List<Vector3> list = new List<Vector3>(pb.vertices);
List<Color> list2 = new List<Color>(pb.colors);
List<Vector2> list3 = new List<Vector2>(pb.uv);
List<pb_Face> list4 = new List<pb_Face>(pb.faces);
pb_IntArray[] sharedIndices = pb.sharedIndices;
int num = pb.vertexCount;
for (int i = 0; i < new_Faces.Length; i++)
{
list.AddRange(new_Vertices[i]);
list2.AddRange(new_Colors[i]);
list3.AddRange(new_uvs[i]);
new_Faces[i].ShiftIndicesToZero();
new_Faces[i].ShiftIndices(num);
new_Faces[i].RebuildCaches();
list4.Add(new_Faces[i]);
if (new_SharedIndices != null && new_Vertices[i].Length != new_SharedIndices[i].Length)
{
Debug.LogError("Append Face failed because sharedIndex array does not match new vertex array.");
return null;
}
if (new_SharedIndices != null)
{
for (int j = 0; j < new_SharedIndices[i].Length; j++)
{
pb_IntArrayUtility.AddValueAtIndex(ref sharedIndices, new_SharedIndices[i][j], j + num);
}
}
else
{
for (int k = 0; k < new_Vertices[i].Length; k++)
{
pb_IntArrayUtility.AddValueAtIndex(ref sharedIndices, -1, k + num);
}
}
num = list.Count;
}
pb.SetSharedIndices(sharedIndices);
pb.SetVertices(list.ToArray());
pb.SetColors(list2.ToArray());
pb.SetUV(list3.ToArray());
pb.SetFaces(list4.ToArray());
return new_Faces;
}
// Token: 0x06000055 RID: 85 RVA: 0x000083C0 File Offset: 0x000067C0
public static void DuplicateAndFlip(this pb_Object pb, pb_Face[] faces)
{
List<pb_FaceRebuildData> list = new List<pb_FaceRebuildData>();
List<pb_Vertex> list2 = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
foreach (pb_Face pb_Face in faces)
{
pb_FaceRebuildData pb_FaceRebuildData = new pb_FaceRebuildData();
pb_FaceRebuildData.vertices = new List<pb_Vertex>();
pb_FaceRebuildData.face = new pb_Face(pb_Face);
pb_FaceRebuildData.sharedIndices = new List<int>();
Dictionary<int, int> dictionary2 = new Dictionary<int, int>();
int num = pb_FaceRebuildData.face.indices.Length;
for (int j = 0; j < num; j++)
{
if (!dictionary2.ContainsKey(pb_Face.indices[j]))
{
dictionary2.Add(pb_Face.indices[j], dictionary2.Count);
pb_FaceRebuildData.vertices.Add(list2[pb_Face.indices[j]]);
pb_FaceRebuildData.sharedIndices.Add(dictionary[pb_Face.indices[j]]);
}
}
for (int k = 0; k < num; k++)
{
pb_FaceRebuildData.face.indices[k] = dictionary2[pb_FaceRebuildData.face.indices[k]];
}
pb_FaceRebuildData.face.ReverseIndices();
list.Add(pb_FaceRebuildData);
}
pb_FaceRebuildData.Apply(list, pb, list2, null, dictionary, null);
}
// Token: 0x06000056 RID: 86 RVA: 0x0000852A File Offset: 0x0000692A
public static int[] DeleteFace(this pb_Object pb, pb_Face face)
{
return pb.DeleteFaces(new pb_Face[] { face });
}
// Token: 0x06000057 RID: 87 RVA: 0x0000853C File Offset: 0x0000693C
public static int[] DeleteFaces(this pb_Object pb, IEnumerable<pb_Face> faces)
{
return pb.DeleteFaces(faces.Select((pb_Face x) => Array.IndexOf<pb_Face>(pb.faces, x)).ToList<int>());
}
// Token: 0x06000058 RID: 88 RVA: 0x00008578 File Offset: 0x00006978
public static int[] DeleteFaces(this pb_Object pb, IList<int> faceIndices)
{
pb_Face[] array = new pb_Face[faceIndices.Count];
for (int i = 0; i < array.Length; i++)
{
array[i] = pb.faces[faceIndices[i]];
}
List<int> list = array.SelectMany((pb_Face x) => x.distinctIndices).Distinct<int>().ToList<int>();
list.Sort();
int num = pb.vertices.Length;
Vector3[] array2 = pb.vertices.SortedRemoveAt(list);
Color[] array3 = pb.colors.SortedRemoveAt(list);
Vector2[] array4 = pb.uv.SortedRemoveAt(list);
pb_Face[] array5 = pb.faces.RemoveAt(faceIndices);
Dictionary<int, int> dictionary = new Dictionary<int, int>();
for (int j = 0; j < num; j++)
{
dictionary.Add(j, pbUtil.NearestIndexPriorToValue<int>(list, j) + 1);
}
for (int k = 0; k < array5.Length; k++)
{
int[] indices = array5[k].indices;
for (int l = 0; l < indices.Length; l++)
{
indices[l] -= dictionary[indices[l]];
}
array5[k].SetIndices(indices);
}
pb_IntArray[] sharedIndices = pb.sharedIndices;
pb_IntArray[] sharedIndicesUV = pb.sharedIndicesUV;
pb_IntArrayUtility.RemoveValuesAndShift(ref sharedIndices, list);
pb_IntArrayUtility.RemoveValuesAndShift(ref sharedIndicesUV, list);
pb.SetSharedIndices(sharedIndices);
pb.SetSharedIndicesUV(sharedIndicesUV);
pb.SetVertices(array2);
pb.SetColors(array3);
pb.SetUV(array4);
pb.SetFaces(array5);
return list.ToArray();
}
}
}
@@ -0,0 +1,231 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ProBuilder2.Common;
using UnityEngine;
namespace ProBuilder2.MeshOperations
{
// Token: 0x02000008 RID: 8
public static class pb_AppendPolygon
{
// Token: 0x0600005A RID: 90 RVA: 0x0000873C File Offset: 0x00006B3C
public static pb_ActionResult CreatePolygon(this pb_Object pb, IList<int> indices, bool unordered, out pb_Face face)
{
pb_IntArray[] sharedIndices = pb.sharedIndices;
Dictionary<int, int> dictionary = sharedIndices.ToDictionary();
HashSet<int> commonIndices = pb_IntArrayUtility.GetCommonIndices(dictionary, indices);
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
List<pb_Vertex> list2 = new List<pb_Vertex>();
foreach (int num in commonIndices)
{
int num2 = sharedIndices[num][0];
list2.Add(new pb_Vertex(list[num2]));
}
pb_FaceRebuildData pb_FaceRebuildData = pb_AppendPolygon.FaceWithVertices(list2, unordered);
if (pb_FaceRebuildData != null)
{
pb_FaceRebuildData.sharedIndices = commonIndices.ToList<int>();
List<pb_Face> list3 = new List<pb_Face>(pb.faces);
pb_FaceRebuildData.Apply(new pb_FaceRebuildData[] { pb_FaceRebuildData }, list, list3, dictionary, null);
pb.SetVertices(list, false);
pb.SetFaces(list3.ToArray());
pb.SetSharedIndices(dictionary);
face = pb_FaceRebuildData.face;
return new pb_ActionResult(Status.Success, "Create Polygon");
}
face = null;
return new pb_ActionResult(Status.Failure, (!unordered) ? "Points not ordered correctly" : "Too Few Unique Points Selected");
}
// Token: 0x0600005B RID: 91 RVA: 0x00008868 File Offset: 0x00006C68
public static pb_ActionResult CreateShapeFromPolygon(this pb_PolyShape poly)
{
return poly.mesh.CreateShapeFromPolygon(poly.points, poly.extrude, poly.flipNormals);
}
// Token: 0x0600005C RID: 92 RVA: 0x00008888 File Offset: 0x00006C88
public static pb_ActionResult CreateShapeFromPolygon(this pb_Object pb, IList<Vector3> points, float extrude, bool flipNormals)
{
if (points.Count < 3)
{
pb.SetVertices(new Vector3[0]);
pb.SetFaces(new pb_Face[0]);
pb.SetSharedIndices(new pb_IntArray[0]);
return new pb_ActionResult(Status.NoChange, "Too Few Points");
}
Vector3[] array = points.ToArray<Vector3>();
pb_Log.PushLogLevel(pb_LogLevel.Error);
List<int> list;
if (!pb_Triangulation.TriangulateVertices(array, out list, false, false))
{
pb_Log.PopLogLevel();
return new pb_ActionResult(Status.Failure, "Failed Triangulating Points");
}
int[] array2 = list.ToArray();
if (pb_Math.PolygonArea(array, array2) < Mathf.Epsilon)
{
pb.SetVertices(new Vector3[0]);
pb.SetFaces(new pb_Face[0]);
pb.SetSharedIndices(new pb_IntArray[0]);
pb_Log.PopLogLevel();
return new pb_ActionResult(Status.Failure, "Polygon Area < Epsilon");
}
pb.GeometryWithVerticesFaces(array, new pb_Face[]
{
new pb_Face(array2)
});
Vector3 vector = pb_Math.Normal(pb, pb.faces[0]);
if (Vector3.Dot(Vector3.up, vector) > 0f)
{
pb.faces[0].ReverseIndices();
}
pb.DuplicateAndFlip(pb.faces);
pb.Extrude(new pb_Face[] { pb.faces[1] }, ExtrudeMethod.IndividualFaces, extrude);
if ((extrude < 0f && !flipNormals) || (extrude > 0f && flipNormals))
{
pb.ReverseWindingOrder(pb.faces);
}
pb_Log.PopLogLevel();
pb.ToMesh();
pb.Refresh(RefreshMask.All);
return new pb_ActionResult(Status.Success, "Create Polygon Shape");
}
// Token: 0x0600005D RID: 93 RVA: 0x00008A0C File Offset: 0x00006E0C
public static pb_FaceRebuildData FaceWithVertices(List<pb_Vertex> vertices, bool unordered = true)
{
List<int> list;
if (pb_Triangulation.TriangulateVertices(vertices, out list, unordered, false))
{
return new pb_FaceRebuildData
{
vertices = vertices,
face = new pb_Face(list.ToArray())
};
}
return null;
}
// Token: 0x0600005E RID: 94 RVA: 0x00008A4C File Offset: 0x00006E4C
public static List<pb_FaceRebuildData> TentCapWithVertices(List<pb_Vertex> path)
{
int count = path.Count;
pb_Vertex pb_Vertex = pb_Vertex.Average(path, null);
List<pb_FaceRebuildData> list = new List<pb_FaceRebuildData>();
for (int i = 0; i < count; i++)
{
List<pb_Vertex> list2 = new List<pb_Vertex>
{
path[i],
pb_Vertex,
path[(i + 1) % count]
};
list.Add(new pb_FaceRebuildData
{
vertices = list2,
face = new pb_Face(new int[] { 0, 1, 2 })
});
}
return list;
}
// Token: 0x0600005F RID: 95 RVA: 0x00008AE8 File Offset: 0x00006EE8
public static List<List<pb_Edge>> FindHoles(pb_Object pb, IList<int> indices)
{
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
HashSet<int> commonIndices = pb_IntArrayUtility.GetCommonIndices(dictionary, indices);
List<List<pb_Edge>> list = new List<List<pb_Edge>>();
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, false);
foreach (List<pb_WingedEdge> list2 in pb_AppendPolygon.FindHoles(wingedEdges, commonIndices))
{
list.Add(list2.Select((pb_WingedEdge x) => x.edge.local).ToList<pb_Edge>());
}
return list;
}
// Token: 0x06000060 RID: 96 RVA: 0x00008B94 File Offset: 0x00006F94
public static List<List<pb_WingedEdge>> FindHoles(List<pb_WingedEdge> wings, HashSet<int> common)
{
HashSet<pb_WingedEdge> hashSet = new HashSet<pb_WingedEdge>();
List<List<pb_WingedEdge>> list = new List<List<pb_WingedEdge>>();
for (int i = 0; i < wings.Count; i++)
{
pb_WingedEdge pb_WingedEdge = wings[i];
if (pb_WingedEdge.opposite == null && !hashSet.Contains(pb_WingedEdge) && (common.Contains(pb_WingedEdge.edge.common.x) || common.Contains(pb_WingedEdge.edge.common.y)))
{
List<pb_WingedEdge> list2 = new List<pb_WingedEdge>();
pb_WingedEdge pb_WingedEdge2 = pb_WingedEdge;
int num = pb_WingedEdge2.edge.common.x;
int num2 = 0;
while (pb_WingedEdge2 != null && num2++ < 2048)
{
hashSet.Add(pb_WingedEdge2);
list2.Add(pb_WingedEdge2);
num = ((pb_WingedEdge2.edge.common.x != num) ? pb_WingedEdge2.edge.common.x : pb_WingedEdge2.edge.common.y);
pb_WingedEdge2 = pb_AppendPolygon.FindNextEdgeInHole(pb_WingedEdge2, num);
if (pb_WingedEdge2 == pb_WingedEdge)
{
break;
}
}
List<pb_Tuple<int, int>> list3 = new List<pb_Tuple<int, int>>();
for (int j = 0; j < list2.Count; j++)
{
pb_WingedEdge pb_WingedEdge3 = list2[j];
for (int k = j - 1; k > -1; k--)
{
if (pb_WingedEdge3.edge.common.y == list2[k].edge.common.x)
{
list3.Add(new pb_Tuple<int, int>(k, j));
break;
}
}
}
int count = list3.Count;
list3.Sort((pb_Tuple<int, int> x, pb_Tuple<int, int> y) => x.Item1.CompareTo(y.Item1));
int[] array = new int[count];
for (int l = count - 1; l > -1; l--)
{
int item = list3[l].Item1;
int num3 = list3[l].Item2 - array[l];
int num4 = num3 - item + 1;
List<pb_WingedEdge> range = list2.GetRange(item, num4);
list2.RemoveRange(item, num4);
for (int m = l - 1; m > -1; m--)
{
if (list3[m].Item2 > list3[l].Item2)
{
array[m] += num4;
}
}
if (count < 2 || range.Any((pb_WingedEdge w) => common.Contains(w.edge.common.x)) || range.Any((pb_WingedEdge w) => common.Contains(w.edge.common.y)))
{
list.Add(range);
}
}
}
}
return list;
}
// Token: 0x06000061 RID: 97 RVA: 0x00008E90 File Offset: 0x00007290
private static pb_WingedEdge FindNextEdgeInHole(pb_WingedEdge wing, int common)
{
pb_WingedEdge pb_WingedEdge = wing.GetAdjacentEdgeWithCommonIndex(common);
int num = 0;
while (pb_WingedEdge != null && pb_WingedEdge != wing && num++ < 2048)
{
if (pb_WingedEdge.opposite == null)
{
return pb_WingedEdge;
}
pb_WingedEdge = pb_WingedEdge.opposite.GetAdjacentEdgeWithCommonIndex(common);
}
return null;
}
// Token: 0x04000014 RID: 20
private const int MAX_HOLE_ITERATIONS = 2048;
}
}
@@ -0,0 +1,274 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ProBuilder2.Common;
using UnityEngine;
namespace ProBuilder2.MeshOperations
{
// Token: 0x02000009 RID: 9
public static class pb_Bevel
{
// Token: 0x06000064 RID: 100 RVA: 0x00008F48 File Offset: 0x00007348
public static pb_ActionResult BevelEdges(pb_Object pb, IList<pb_Edge> edges, float amount, out List<pb_Face> createdFaces)
{
createdFaces = null;
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
List<pb_EdgeLookup> list2 = pb_EdgeLookup.GetEdgeLookup(edges, dictionary).Distinct<pb_EdgeLookup>().ToList<pb_EdgeLookup>();
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, false);
List<pb_FaceRebuildData> list3 = new List<pb_FaceRebuildData>();
Dictionary<pb_Face, List<int>> ignore = new Dictionary<pb_Face, List<int>>();
HashSet<int> hashSet = new HashSet<int>();
int num = 0;
Dictionary<int, List<pb_Tuple<pb_FaceRebuildData, List<int>>>> dictionary2 = new Dictionary<int, List<pb_Tuple<pb_FaceRebuildData, List<int>>>>();
Dictionary<int, List<pb_WingedEdge>> spokes = pb_WingedEdge.GetSpokes(wingedEdges);
HashSet<int> hashSet2 = new HashSet<int>();
foreach (pb_EdgeLookup pb_EdgeLookup in list2)
{
if (hashSet2.Add(pb_EdgeLookup.common.x))
{
foreach (pb_WingedEdge pb_WingedEdge in spokes[pb_EdgeLookup.common.x])
{
pb_Edge local = pb_WingedEdge.edge.local;
amount = Mathf.Min(Vector3.Distance(list[local.x].position, list[local.y].position) - 0.001f, amount);
}
}
if (hashSet2.Add(pb_EdgeLookup.common.y))
{
foreach (pb_WingedEdge pb_WingedEdge2 in spokes[pb_EdgeLookup.common.y])
{
pb_Edge local2 = pb_WingedEdge2.edge.local;
amount = Mathf.Min(Vector3.Distance(list[local2.x].position, list[local2.y].position) - 0.001f, amount);
}
}
}
if (amount < 0.001f)
{
return new pb_ActionResult(Status.Canceled, "Bevel Distance > Available Surface");
}
using (List<pb_EdgeLookup>.Enumerator enumerator4 = list2.GetEnumerator())
{
while (enumerator4.MoveNext())
{
pb_EdgeLookup lup = enumerator4.Current;
pb_WingedEdge pb_WingedEdge3 = wingedEdges.FirstOrDefault((pb_WingedEdge x) => x.edge.Equals(lup));
if (pb_WingedEdge3 != null && pb_WingedEdge3.opposite != null)
{
num++;
ignore.AddOrAppend(pb_WingedEdge3.face, pb_WingedEdge3.edge.common.x);
ignore.AddOrAppend(pb_WingedEdge3.face, pb_WingedEdge3.edge.common.y);
ignore.AddOrAppend(pb_WingedEdge3.opposite.face, pb_WingedEdge3.edge.common.x);
ignore.AddOrAppend(pb_WingedEdge3.opposite.face, pb_WingedEdge3.edge.common.y);
hashSet.Add(pb_WingedEdge3.edge.common.x);
hashSet.Add(pb_WingedEdge3.edge.common.y);
pb_Bevel.SlideEdge(list, pb_WingedEdge3, amount);
pb_Bevel.SlideEdge(list, pb_WingedEdge3.opposite, amount);
list3.AddRange(pb_Bevel.GetBridgeFaces(list, pb_WingedEdge3, pb_WingedEdge3.opposite, dictionary2));
}
}
}
if (num < 1)
{
createdFaces = null;
return new pb_ActionResult(Status.Canceled, "Cannot Bevel Open Edges");
}
createdFaces = new List<pb_Face>(list3.Select((pb_FaceRebuildData x) => x.face));
Dictionary<pb_Face, List<pb_Tuple<pb_WingedEdge, int>>> dictionary3 = new Dictionary<pb_Face, List<pb_Tuple<pb_WingedEdge, int>>>();
using (HashSet<int>.Enumerator enumerator5 = hashSet.GetEnumerator())
{
while (enumerator5.MoveNext())
{
int c = enumerator5.Current;
IEnumerable<pb_WingedEdge> enumerable = wingedEdges.Where((pb_WingedEdge x) => x.edge.common.Contains(c) && (!ignore.ContainsKey(x.face) || !ignore[x.face].Contains(c)));
HashSet<pb_Face> hashSet3 = new HashSet<pb_Face>();
foreach (pb_WingedEdge pb_WingedEdge4 in enumerable)
{
if (hashSet3.Add(pb_WingedEdge4.face))
{
dictionary3.AddOrAppend(pb_WingedEdge4.face, new pb_Tuple<pb_WingedEdge, int>(pb_WingedEdge4, c));
}
}
}
}
foreach (KeyValuePair<pb_Face, List<pb_Tuple<pb_WingedEdge, int>>> keyValuePair in dictionary3)
{
Dictionary<int, List<int>> dictionary4;
pb_FaceRebuildData pb_FaceRebuildData = pbVertexOps.ExplodeVertex(list, keyValuePair.Value, amount, out dictionary4);
if (pb_FaceRebuildData != null)
{
list3.Add(pb_FaceRebuildData);
foreach (KeyValuePair<int, List<int>> keyValuePair2 in dictionary4)
{
dictionary2.AddOrAppend(keyValuePair2.Key, new pb_Tuple<pb_FaceRebuildData, List<int>>(pb_FaceRebuildData, keyValuePair2.Value));
}
}
}
pb_FaceRebuildData.Apply(list3, pb, list, null, null, null);
int num2 = pb.DeleteFaces(dictionary3.Keys).Length;
pb.SetSharedIndicesUV(new pb_IntArray[0]);
pb.SetSharedIndices(pb_IntArrayUtility.ExtractSharedIndices(pb.vertices));
pb_IntArray[] sharedIndices = pb.sharedIndices;
dictionary = sharedIndices.ToDictionary();
List<HashSet<int>> list4 = new List<HashSet<int>>();
foreach (KeyValuePair<int, List<pb_Tuple<pb_FaceRebuildData, List<int>>>> keyValuePair3 in dictionary2)
{
if (keyValuePair3.Value.Sum((pb_Tuple<pb_FaceRebuildData, List<int>> x) => x.Item2.Count) >= 3)
{
HashSet<int> hashSet4 = new HashSet<int>();
foreach (pb_Tuple<pb_FaceRebuildData, List<int>> pb_Tuple in keyValuePair3.Value)
{
int num3 = pb_Tuple.Item1.Offset() - num2;
for (int i = 0; i < pb_Tuple.Item2.Count; i++)
{
hashSet4.Add(dictionary[pb_Tuple.Item2[i] + num3]);
}
}
list4.Add(hashSet4);
}
}
List<pb_WingedEdge> wingedEdges2 = pb_WingedEdge.GetWingedEdges(pb, list3.Select((pb_FaceRebuildData x) => x.face), false, null);
list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
List<pb_FaceRebuildData> list5 = new List<pb_FaceRebuildData>();
foreach (HashSet<int> hashSet5 in list4)
{
if (hashSet5.Count >= 3)
{
if (hashSet5.Count < 4)
{
List<pb_Vertex> list6 = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, hashSet5.Select((int x) => sharedIndices[x][0]).ToList<int>()));
list5.Add(pb_AppendPolygon.FaceWithVertices(list6, true));
}
else
{
List<int> list7 = pb_WingedEdge.SortCommonIndicesByAdjacency(wingedEdges2, hashSet5);
List<pb_Vertex> list8 = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, list7.Select((int x) => sharedIndices[x][0]).ToList<int>()));
list5.AddRange(pb_AppendPolygon.TentCapWithVertices(list8));
}
}
}
pb_FaceRebuildData.Apply(list5, pb, list, null, null, null);
pb.SetSharedIndices(pb_IntArrayUtility.ExtractSharedIndices(pb.vertices));
HashSet<pb_Face> hashSet6 = new HashSet<pb_Face>(list5.Select((pb_FaceRebuildData x) => x.face));
list3.AddRange(list5);
List<pb_WingedEdge> wingedEdges3 = pb_WingedEdge.GetWingedEdges(pb, list3.Select((pb_FaceRebuildData x) => x.face), false, null);
int num4 = 0;
while (num4 < wingedEdges3.Count && hashSet6.Count > 0)
{
pb_WingedEdge pb_WingedEdge5 = wingedEdges3[num4];
if (hashSet6.Contains(pb_WingedEdge5.face))
{
hashSet6.Remove(pb_WingedEdge5.face);
pb_WingedEdgeEnumerator enumerator12 = pb_WingedEdge5.GetEnumerator();
try
{
while (enumerator12.MoveNext())
{
pb_WingedEdge pb_WingedEdge6 = enumerator12.Current;
if (!hashSet6.Contains(pb_WingedEdge6.opposite.face))
{
pb_WingedEdge6.face.material = pb_WingedEdge6.opposite.face.material;
pb_WingedEdge6.face.uv = new pb_UV(pb_WingedEdge6.opposite.face.uv);
pb_ConformNormals.ConformOppositeNormal(pb_WingedEdge6.opposite);
break;
}
}
}
finally
{
IDisposable disposable;
if ((disposable = enumerator12 as IDisposable) != null)
{
disposable.Dispose();
}
}
}
num4++;
}
pb.ToMesh();
return new pb_ActionResult(Status.Success, "Bevel Edges");
}
// Token: 0x06000065 RID: 101 RVA: 0x000099B0 File Offset: 0x00007DB0
private static List<pb_FaceRebuildData> GetBridgeFaces(IList<pb_Vertex> vertices, pb_WingedEdge left, pb_WingedEdge right, Dictionary<int, List<pb_Tuple<pb_FaceRebuildData, List<int>>>> holes)
{
List<pb_FaceRebuildData> list = new List<pb_FaceRebuildData>();
pb_FaceRebuildData pb_FaceRebuildData = new pb_FaceRebuildData();
pb_EdgeLookup edge = left.edge;
pb_EdgeLookup edge2 = right.edge;
pb_FaceRebuildData.vertices = new List<pb_Vertex>
{
vertices[edge.local.x],
vertices[edge.local.y],
vertices[(edge.common.x != edge2.common.x) ? edge2.local.y : edge2.local.x],
vertices[(edge.common.x != edge2.common.x) ? edge2.local.x : edge2.local.y]
};
Vector3 vector = pb_Math.Normal(vertices, left.face.indices);
Vector3 vector2 = pb_Math.Normal(pb_FaceRebuildData.vertices, pb_Bevel.BRIDGE_INDICES_NRM);
int[] array = new int[] { 2, 1, 0, 2, 3, 1 };
if (Vector3.Dot(vector, vector2) < 0f)
{
Array.Reverse(array);
}
pb_FaceRebuildData.face = new pb_Face(array, left.face.material, new pb_UV(), -1, -1, -1, false);
list.Add(pb_FaceRebuildData);
holes.AddOrAppend(edge.common.x, new pb_Tuple<pb_FaceRebuildData, List<int>>(pb_FaceRebuildData, new List<int> { 0, 2 }));
holes.AddOrAppend(edge.common.y, new pb_Tuple<pb_FaceRebuildData, List<int>>(pb_FaceRebuildData, new List<int> { 1, 3 }));
return list;
}
// Token: 0x06000066 RID: 102 RVA: 0x00009B78 File Offset: 0x00007F78
private static void SlideEdge(IList<pb_Vertex> vertices, pb_WingedEdge we, float amount)
{
we.face.manualUV = true;
we.face.textureGroup = -1;
pb_Edge leadingEdge = pb_Bevel.GetLeadingEdge(we, we.edge.common.x);
pb_Edge leadingEdge2 = pb_Bevel.GetLeadingEdge(we, we.edge.common.y);
if (leadingEdge == null || leadingEdge2 == null)
{
return;
}
pb_Vertex pb_Vertex = vertices[leadingEdge.x] - vertices[leadingEdge.y];
pb_Vertex.Normalize();
pb_Vertex pb_Vertex2 = vertices[leadingEdge2.x] - vertices[leadingEdge2.y];
pb_Vertex2.Normalize();
vertices[we.edge.local.x].Add(pb_Vertex * amount);
vertices[we.edge.local.y].Add(pb_Vertex2 * amount);
}
// Token: 0x06000067 RID: 103 RVA: 0x00009C64 File Offset: 0x00008064
private static pb_Edge GetLeadingEdge(pb_WingedEdge wing, int common)
{
if (wing.previous.edge.common.x == common)
{
return new pb_Edge(wing.previous.edge.local.y, wing.previous.edge.local.x);
}
if (wing.previous.edge.common.y == common)
{
return new pb_Edge(wing.previous.edge.local.x, wing.previous.edge.local.y);
}
if (wing.next.edge.common.x == common)
{
return new pb_Edge(wing.next.edge.local.y, wing.next.edge.local.x);
}
if (wing.next.edge.common.y == common)
{
return new pb_Edge(wing.next.edge.local.x, wing.next.edge.local.y);
}
return null;
}
// Token: 0x06000068 RID: 104 RVA: 0x00009D9E File Offset: 0x0000819E
// Note: this type is marked as 'beforefieldinit'.
static pb_Bevel()
{
int[] array = new int[3];
array[0] = 2;
array[1] = 1;
pb_Bevel.BRIDGE_INDICES_NRM = array;
}
// Token: 0x04000017 RID: 23
private static readonly int[] BRIDGE_INDICES_NRM;
}
}
@@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ProBuilder2.Common;
namespace ProBuilder2.MeshOperations
{
// Token: 0x0200000A RID: 10
public static class pb_ConformNormals
{
// Token: 0x0600006E RID: 110 RVA: 0x00009E9C File Offset: 0x0000829C
public static pb_ActionResult ConformNormals(this pb_Object pb, IList<pb_Face> faces)
{
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, faces, false, null);
HashSet<pb_Face> hashSet = new HashSet<pb_Face>();
int num = 0;
for (int i = 0; i < wingedEdges.Count; i++)
{
if (!hashSet.Contains(wingedEdges[i].face))
{
Dictionary<pb_Face, bool> dictionary = new Dictionary<pb_Face, bool>();
pb_ConformNormals.GetWindingFlags(wingedEdges[i], true, dictionary);
int num2 = 0;
foreach (KeyValuePair<pb_Face, bool> keyValuePair in dictionary)
{
num2 += ((!keyValuePair.Value) ? (-1) : 1);
}
bool flag = num2 > 0;
foreach (KeyValuePair<pb_Face, bool> keyValuePair2 in dictionary)
{
if (flag != keyValuePair2.Value)
{
num++;
keyValuePair2.Key.ReverseIndices();
}
}
hashSet.UnionWith(dictionary.Keys);
}
}
if (num > 0)
{
return new pb_ActionResult(Status.Success, (num <= 1) ? "Flipped 1 face" : string.Format("Flipped {0} faces", num));
}
return new pb_ActionResult(Status.NoChange, "Faces Uniform");
}
// Token: 0x0600006F RID: 111 RVA: 0x0000A014 File Offset: 0x00008414
private static void GetWindingFlags(pb_WingedEdge edge, bool flag, Dictionary<pb_Face, bool> flags)
{
flags.Add(edge.face, flag);
pb_WingedEdge pb_WingedEdge = edge;
do
{
pb_WingedEdge opposite = pb_WingedEdge.opposite;
if (opposite != null && !flags.ContainsKey(opposite.face))
{
pb_Edge commonEdgeInWindingOrder = pb_ConformNormals.GetCommonEdgeInWindingOrder(pb_WingedEdge);
pb_Edge commonEdgeInWindingOrder2 = pb_ConformNormals.GetCommonEdgeInWindingOrder(opposite);
pb_ConformNormals.GetWindingFlags(opposite, (commonEdgeInWindingOrder.x != commonEdgeInWindingOrder2.x) ? flag : (!flag), flags);
}
pb_WingedEdge = pb_WingedEdge.next;
}
while (pb_WingedEdge != edge);
}
// Token: 0x06000070 RID: 112 RVA: 0x0000A08C File Offset: 0x0000848C
public static pb_ActionResult ConformOppositeNormal(pb_WingedEdge source)
{
if (source == null || source.opposite == null)
{
return new pb_ActionResult(Status.Failure, "Source edge does not share an edge with another face.");
}
pb_Edge commonEdgeInWindingOrder = pb_ConformNormals.GetCommonEdgeInWindingOrder(source);
pb_Edge commonEdgeInWindingOrder2 = pb_ConformNormals.GetCommonEdgeInWindingOrder(source.opposite);
if (commonEdgeInWindingOrder.x == commonEdgeInWindingOrder2.x)
{
source.opposite.face.ReverseIndices();
return new pb_ActionResult(Status.Success, "Reversed target face winding order.");
}
return new pb_ActionResult(Status.NoChange, "Faces already unified.");
}
// Token: 0x06000071 RID: 113 RVA: 0x0000A104 File Offset: 0x00008504
private static pb_Edge GetCommonEdgeInWindingOrder(pb_WingedEdge wing)
{
int[] indices = wing.face.indices;
int num = indices.Length;
for (int i = 0; i < num; i += 3)
{
pb_Edge local = wing.edge.local;
int num2 = indices[i];
int num3 = indices[i + 1];
int num4 = indices[i + 2];
if (local.x == num2 && local.y == num3)
{
return new pb_Edge(wing.edge.common);
}
if (local.x == num3 && local.y == num2)
{
return new pb_Edge(wing.edge.common.y, wing.edge.common.x);
}
if (local.x == num3 && local.y == num4)
{
return new pb_Edge(wing.edge.common);
}
if (local.x == num4 && local.y == num3)
{
return new pb_Edge(wing.edge.common.y, wing.edge.common.x);
}
if (local.x == num4 && local.y == num2)
{
return new pb_Edge(wing.edge.common);
}
if (local.x == num2 && local.y == num4)
{
return new pb_Edge(wing.edge.common.y, wing.edge.common.x);
}
}
return null;
}
// Token: 0x06000072 RID: 114 RVA: 0x0000A294 File Offset: 0x00008694
public static void MatchNormal(pb_Face source, pb_Face target, Dictionary<int, int> lookup)
{
List<pb_EdgeLookup> list = pb_EdgeLookup.GetEdgeLookup(source.edges, lookup).ToList<pb_EdgeLookup>();
List<pb_EdgeLookup> list2 = pb_EdgeLookup.GetEdgeLookup(target.edges, lookup).ToList<pb_EdgeLookup>();
bool flag = false;
int num = 0;
while (!flag && num < list.Count)
{
pb_Edge common = list[num].common;
int num2 = 0;
while (!flag && num2 < list2.Count)
{
pb_Edge common2 = list2[num2].common;
if (common.Equals(common2))
{
if (common.x == common2.x)
{
target.ReverseIndices();
}
flag = true;
}
num2++;
}
num++;
}
}
}
}
@@ -0,0 +1,262 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ProBuilder2.Common;
using UnityEngine;
namespace ProBuilder2.MeshOperations
{
// Token: 0x0200000C RID: 12
public static class pb_ConnectEdges
{
// Token: 0x06000074 RID: 116 RVA: 0x0000A364 File Offset: 0x00008764
public static pb_ActionResult Connect(this pb_Object pb, IEnumerable<pb_Face> faces, out pb_Face[] subdividedFaces)
{
IEnumerable<pb_Edge> enumerable = faces.SelectMany((pb_Face x) => x.edges);
HashSet<pb_Face> hashSet = new HashSet<pb_Face>(faces);
pb_Edge[] array;
return pb.Connect(enumerable, out subdividedFaces, out array, true, false, hashSet);
}
// Token: 0x06000075 RID: 117 RVA: 0x0000A3AC File Offset: 0x000087AC
public static pb_ActionResult Connect(this pb_Object pb, IEnumerable<pb_Edge> edges, out pb_Face[] faces)
{
pb_Edge[] array;
return pb.Connect(edges, out faces, out array, true, false, null);
}
// Token: 0x06000076 RID: 118 RVA: 0x0000A3C8 File Offset: 0x000087C8
public static pb_ActionResult Connect(this pb_Object pb, IEnumerable<pb_Edge> edges, out pb_Edge[] connections)
{
pb_Face[] array;
return pb.Connect(edges, out array, out connections, false, true, null);
}
// Token: 0x06000077 RID: 119 RVA: 0x0000A3E4 File Offset: 0x000087E4
private static pb_ActionResult Connect(this pb_Object pb, IEnumerable<pb_Edge> edges, out pb_Face[] addedFaces, out pb_Edge[] connections, bool returnFaces = false, bool returnEdges = false, HashSet<pb_Face> faceMask = null)
{
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
Dictionary<int, int> dictionary2 = ((pb.sharedIndicesUV == null) ? null : pb.sharedIndicesUV.ToDictionary());
HashSet<pb_EdgeLookup> hashSet = new HashSet<pb_EdgeLookup>(pb_EdgeLookup.GetEdgeLookup(edges, dictionary));
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, false);
Dictionary<pb_Face, List<pb_WingedEdge>> dictionary3 = new Dictionary<pb_Face, List<pb_WingedEdge>>();
foreach (pb_WingedEdge pb_WingedEdge in wingedEdges)
{
if (hashSet.Contains(pb_WingedEdge.edge))
{
List<pb_WingedEdge> list;
if (dictionary3.TryGetValue(pb_WingedEdge.face, out list))
{
list.Add(pb_WingedEdge);
}
else
{
dictionary3.Add(pb_WingedEdge.face, new List<pb_WingedEdge> { pb_WingedEdge });
}
}
}
Dictionary<pb_Face, List<pb_WingedEdge>> dictionary4 = new Dictionary<pb_Face, List<pb_WingedEdge>>();
foreach (KeyValuePair<pb_Face, List<pb_WingedEdge>> keyValuePair in dictionary3)
{
if (keyValuePair.Value.Count <= 1)
{
pb_WingedEdge opposite = keyValuePair.Value[0].opposite;
if (opposite == null)
{
continue;
}
List<pb_WingedEdge> list2;
if (!dictionary3.TryGetValue(opposite.face, out list2))
{
continue;
}
if (list2.Count <= 1)
{
continue;
}
}
dictionary4.Add(keyValuePair.Key, keyValuePair.Value);
}
List<pb_Vertex> list3 = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
List<ConnectFaceRebuildData> list4 = new List<ConnectFaceRebuildData>();
List<pb_Face> list5 = new List<pb_Face>();
HashSet<int> hashSet2 = new HashSet<int>(pb.faces.Select((pb_Face x) => x.textureGroup));
int num = 1;
foreach (KeyValuePair<pb_Face, List<pb_WingedEdge>> keyValuePair2 in dictionary4)
{
pb_Face key = keyValuePair2.Key;
List<pb_WingedEdge> value = keyValuePair2.Value;
int count = value.Count;
Vector3 vector = pb_Math.Normal(list3, key.indices);
if (count == 1 || (faceMask != null && !faceMask.Contains(key)))
{
ConnectFaceRebuildData connectFaceRebuildData = pb_ConnectEdges.InsertVertices(key, value, list3);
Vector3 vector2 = pb_Math.Normal(connectFaceRebuildData.faceRebuildData.vertices, connectFaceRebuildData.faceRebuildData.face.indices);
if (Vector3.Dot(vector, vector2) < 0f)
{
connectFaceRebuildData.faceRebuildData.face.ReverseIndices();
}
list4.Add(connectFaceRebuildData);
}
else if (count > 1)
{
List<ConnectFaceRebuildData> list6 = ((count != 2) ? pb_ConnectEdges.ConnectEdgesInFace(key, value, list3) : pb_ConnectEdges.ConnectEdgesInFace(key, value[0], value[1], list3));
if (key.textureGroup < 0)
{
while (hashSet2.Contains(num))
{
num++;
}
hashSet2.Add(num);
}
foreach (ConnectFaceRebuildData connectFaceRebuildData2 in list6)
{
list5.Add(connectFaceRebuildData2.faceRebuildData.face);
Vector3 vector3 = pb_Math.Normal(connectFaceRebuildData2.faceRebuildData.vertices, connectFaceRebuildData2.faceRebuildData.face.indices);
if (Vector3.Dot(vector, vector3) < 0f)
{
connectFaceRebuildData2.faceRebuildData.face.ReverseIndices();
}
connectFaceRebuildData2.faceRebuildData.face.textureGroup = ((key.textureGroup >= 0) ? key.textureGroup : num);
connectFaceRebuildData2.faceRebuildData.face.uv = new pb_UV(key.uv);
connectFaceRebuildData2.faceRebuildData.face.smoothingGroup = key.smoothingGroup;
connectFaceRebuildData2.faceRebuildData.face.manualUV = key.manualUV;
connectFaceRebuildData2.faceRebuildData.face.material = key.material;
}
list4.AddRange(list6);
}
}
pb_FaceRebuildData.Apply(list4.Select((ConnectFaceRebuildData x) => x.faceRebuildData), pb, list3, null, dictionary, dictionary2);
pb.SetSharedIndicesUV(new pb_IntArray[0]);
int num2 = pb.DeleteFaces(dictionary4.Keys).Length;
pb.SetSharedIndices(pb_IntArrayUtility.ExtractSharedIndices(pb.vertices));
pb.ToMesh();
if (returnEdges)
{
HashSet<int> appendedIndices = new HashSet<int>();
for (int i = 0; i < list4.Count; i++)
{
for (int j = 0; j < list4[i].newVertexIndices.Count; j++)
{
appendedIndices.Add(list4[i].newVertexIndices[j] + list4[i].faceRebuildData.Offset() - num2);
}
}
Dictionary<int, int> dictionary5 = pb.sharedIndices.ToDictionary();
IEnumerable<pb_Edge> enumerable = from x in list4.SelectMany((ConnectFaceRebuildData x) => x.faceRebuildData.face.edges)
where appendedIndices.Contains(x.x) && appendedIndices.Contains(x.y)
select x;
IEnumerable<pb_EdgeLookup> edgeLookup = pb_EdgeLookup.GetEdgeLookup(enumerable, dictionary5);
connections = (from x in edgeLookup.Distinct<pb_EdgeLookup>()
select x.local).ToArray<pb_Edge>();
}
else
{
connections = null;
}
if (returnFaces)
{
addedFaces = list5.ToArray();
}
else
{
addedFaces = null;
}
return new pb_ActionResult(Status.Success, string.Format("Connected {0} Edges", list4.Count));
}
// Token: 0x06000078 RID: 120 RVA: 0x0000AA50 File Offset: 0x00008E50
private static List<ConnectFaceRebuildData> ConnectEdgesInFace(pb_Face face, pb_WingedEdge a, pb_WingedEdge b, List<pb_Vertex> vertices)
{
List<pb_Edge> list = pb_WingedEdge.SortEdgesByAdjacency(face);
List<pb_Vertex>[] array = new List<pb_Vertex>[]
{
new List<pb_Vertex>(),
new List<pb_Vertex>()
};
List<int>[] array2 = new List<int>[]
{
new List<int>(),
new List<int>()
};
int num = 0;
for (int i = 0; i < list.Count; i++)
{
array[num % 2].Add(vertices[list[i].x]);
if (list[i].Equals(a.edge.local) || list[i].Equals(b.edge.local))
{
pb_Vertex pb_Vertex = pb_Vertex.Mix(vertices[list[i].x], vertices[list[i].y], 0.5f);
array2[num % 2].Add(array[num % 2].Count);
array[num % 2].Add(pb_Vertex);
num++;
array2[num % 2].Add(array[num % 2].Count);
array[num % 2].Add(pb_Vertex);
}
}
List<ConnectFaceRebuildData> list2 = new List<ConnectFaceRebuildData>();
for (int j = 0; j < array.Length; j++)
{
pb_FaceRebuildData pb_FaceRebuildData = pb_AppendPolygon.FaceWithVertices(array[j], false);
list2.Add(new ConnectFaceRebuildData(pb_FaceRebuildData, array2[j]));
}
return list2;
}
// Token: 0x06000079 RID: 121 RVA: 0x0000ABBC File Offset: 0x00008FBC
private static List<ConnectFaceRebuildData> ConnectEdgesInFace(pb_Face face, List<pb_WingedEdge> edges, List<pb_Vertex> vertices)
{
List<pb_Edge> list = pb_WingedEdge.SortEdgesByAdjacency(face);
int count = edges.Count;
pb_Vertex pb_Vertex = pb_Vertex.Average(vertices, face.distinctIndices);
List<List<pb_Vertex>> list2 = pbUtil.Fill<List<pb_Vertex>>((int x) => new List<pb_Vertex>(), count);
List<List<int>> list3 = pbUtil.Fill<List<int>>((int x) => new List<int>(), count);
HashSet<pb_Edge> hashSet = new HashSet<pb_Edge>(edges.Select((pb_WingedEdge x) => x.edge.local));
int num = 0;
for (int i = 0; i < list.Count; i++)
{
list2[num % count].Add(vertices[list[i].x]);
if (hashSet.Contains(list[i]))
{
pb_Vertex pb_Vertex2 = pb_Vertex.Mix(vertices[list[i].x], vertices[list[i].y], 0.5f);
list3[num].Add(list2[num].Count);
list2[num].Add(pb_Vertex2);
list3[num].Add(list2[num].Count);
list2[num].Add(pb_Vertex);
num = (num + 1) % count;
list2[num].Add(pb_Vertex2);
}
}
List<ConnectFaceRebuildData> list4 = new List<ConnectFaceRebuildData>();
for (int j = 0; j < list2.Count; j++)
{
pb_FaceRebuildData pb_FaceRebuildData = pb_AppendPolygon.FaceWithVertices(list2[j], false);
list4.Add(new ConnectFaceRebuildData(pb_FaceRebuildData, list3[j]));
}
return list4;
}
// Token: 0x0600007A RID: 122 RVA: 0x0000AD94 File Offset: 0x00009194
private static ConnectFaceRebuildData InsertVertices(pb_Face face, List<pb_WingedEdge> edges, List<pb_Vertex> vertices)
{
List<pb_Edge> list = pb_WingedEdge.SortEdgesByAdjacency(face);
List<pb_Vertex> list2 = new List<pb_Vertex>();
List<int> list3 = new List<int>();
HashSet<pb_Edge> hashSet = new HashSet<pb_Edge>(edges.Select((pb_WingedEdge x) => x.edge.local));
for (int i = 0; i < list.Count; i++)
{
list2.Add(vertices[list[i].x]);
if (hashSet.Contains(list[i]))
{
list3.Add(list2.Count);
list2.Add(pb_Vertex.Mix(vertices[list[i].x], vertices[list[i].y], 0.5f));
}
}
pb_FaceRebuildData pb_FaceRebuildData = pb_AppendPolygon.FaceWithVertices(list2, false);
pb_FaceRebuildData.face.textureGroup = face.textureGroup;
pb_FaceRebuildData.face.uv = new pb_UV(face.uv);
pb_FaceRebuildData.face.smoothingGroup = face.smoothingGroup;
pb_FaceRebuildData.face.manualUV = face.manualUV;
pb_FaceRebuildData.face.material = face.material;
return new ConnectFaceRebuildData(pb_FaceRebuildData, list3);
}
}
}
@@ -0,0 +1,186 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ProBuilder2.Common;
using UnityEngine;
namespace ProBuilder2.MeshOperations
{
// Token: 0x0200000D RID: 13
public static class pb_ConnectVertices
{
// Token: 0x06000084 RID: 132 RVA: 0x0000AF64 File Offset: 0x00009364
public static pb_ActionResult Connect(this pb_Object pb, IList<int> indices, out int[] newVertices)
{
int num = pb.sharedIndices.Length;
Dictionary<int, int> lookup = pb.sharedIndices.ToDictionary();
HashSet<int> hashSet = new HashSet<int>(indices.Select((int x) => lookup[x]));
HashSet<int> hashSet2 = new HashSet<int>();
foreach (int num2 in hashSet)
{
hashSet2.UnionWith(pb.sharedIndices[num2].array);
}
Dictionary<pb_Face, List<int>> dictionary = new Dictionary<pb_Face, List<int>>();
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
foreach (pb_Face pb_Face in pb.faces)
{
int[] distinctIndices = pb_Face.distinctIndices;
for (int j = 0; j < distinctIndices.Length; j++)
{
if (hashSet2.Contains(distinctIndices[j]))
{
dictionary.AddOrAppend(pb_Face, distinctIndices[j]);
}
}
}
List<ConnectFaceRebuildData> list2 = new List<ConnectFaceRebuildData>();
List<pb_Face> list3 = new List<pb_Face>();
HashSet<int> hashSet3 = new HashSet<int>(pb.faces.Select((pb_Face x) => x.textureGroup));
int num3 = 1;
foreach (KeyValuePair<pb_Face, List<int>> keyValuePair in dictionary)
{
pb_Face key = keyValuePair.Key;
List<ConnectFaceRebuildData> list4 = ((keyValuePair.Value.Count != 2) ? pb_ConnectVertices.ConnectIndicesInFace(key, keyValuePair.Value, list, lookup, num++) : pb_ConnectVertices.ConnectIndicesInFace(key, keyValuePair.Value[0], keyValuePair.Value[1], list, lookup));
if (list4 != null)
{
if (key.textureGroup < 0)
{
while (hashSet3.Contains(num3))
{
num3++;
}
hashSet3.Add(num3);
}
foreach (ConnectFaceRebuildData connectFaceRebuildData in list4)
{
connectFaceRebuildData.faceRebuildData.face.textureGroup = ((key.textureGroup >= 0) ? key.textureGroup : num3);
connectFaceRebuildData.faceRebuildData.face.uv = new pb_UV(key.uv);
connectFaceRebuildData.faceRebuildData.face.smoothingGroup = key.smoothingGroup;
connectFaceRebuildData.faceRebuildData.face.manualUV = key.manualUV;
connectFaceRebuildData.faceRebuildData.face.material = key.material;
}
list3.Add(key);
list2.AddRange(list4);
}
}
pb_FaceRebuildData.Apply(list2.Select((ConnectFaceRebuildData x) => x.faceRebuildData), pb, list, null, lookup, null);
pb.SetSharedIndices(lookup);
pb.SetSharedIndicesUV(new pb_IntArray[0]);
int num4 = pb.DeleteFaces(list3).Length;
lookup = pb.sharedIndices.ToDictionary();
HashSet<int> hashSet4 = new HashSet<int>();
for (int k = 0; k < list2.Count; k++)
{
for (int l = 0; l < list2[k].newVertexIndices.Count; l++)
{
hashSet4.Add(lookup[list2[k].newVertexIndices[l] + (list2[k].faceRebuildData.Offset() - num4)]);
}
}
newVertices = hashSet4.Select((int x) => pb.sharedIndices[x][0]).ToArray<int>();
pb.ToMesh();
return new pb_ActionResult(Status.Success, string.Format("Connected {0} Vertices", hashSet.Count));
}
// Token: 0x06000085 RID: 133 RVA: 0x0000B424 File Offset: 0x00009824
private static List<ConnectFaceRebuildData> ConnectIndicesInFace(pb_Face face, int a, int b, List<pb_Vertex> vertices, Dictionary<int, int> lookup)
{
List<pb_Edge> list = pb_WingedEdge.SortEdgesByAdjacency(face);
List<pb_Vertex>[] array = new List<pb_Vertex>[]
{
new List<pb_Vertex>(),
new List<pb_Vertex>()
};
List<int>[] array2 = new List<int>[]
{
new List<int>(),
new List<int>()
};
List<int>[] array3 = new List<int>[]
{
new List<int>(),
new List<int>()
};
int num = 0;
for (int i = 0; i < list.Count; i++)
{
if (list[i].Contains(a) && list[i].Contains(b))
{
return null;
}
int x = list[i].x;
array[num].Add(vertices[x]);
array2[num].Add(lookup[x]);
if (x == a || x == b)
{
num = (num + 1) % 2;
array3[num].Add(array[num].Count);
array[num].Add(vertices[x]);
array2[num].Add(lookup[x]);
}
}
List<ConnectFaceRebuildData> list2 = new List<ConnectFaceRebuildData>();
Vector3 vector = pb_Math.Normal(vertices, face.indices);
for (int j = 0; j < array.Length; j++)
{
pb_FaceRebuildData pb_FaceRebuildData = pb_AppendPolygon.FaceWithVertices(array[j], false);
pb_FaceRebuildData.sharedIndices = array2[j];
Vector3 vector2 = pb_Math.Normal(array[j], pb_FaceRebuildData.face.indices);
if (Vector3.Dot(vector, vector2) < 0f)
{
pb_FaceRebuildData.face.ReverseIndices();
}
list2.Add(new ConnectFaceRebuildData(pb_FaceRebuildData, array3[j]));
}
return list2;
}
// Token: 0x06000086 RID: 134 RVA: 0x0000B5D0 File Offset: 0x000099D0
private static List<ConnectFaceRebuildData> ConnectIndicesInFace(pb_Face face, List<int> indices, List<pb_Vertex> vertices, Dictionary<int, int> lookup, int sharedIndexOffset)
{
if (indices.Count < 3)
{
return null;
}
List<pb_Edge> list = pb_WingedEdge.SortEdgesByAdjacency(face);
int count = indices.Count;
List<List<pb_Vertex>> list2 = pbUtil.Fill<List<pb_Vertex>>((int x) => new List<pb_Vertex>(), count);
List<List<int>> list3 = pbUtil.Fill<List<int>>((int x) => new List<int>(), count);
List<List<int>> list4 = pbUtil.Fill<List<int>>((int x) => new List<int>(), count);
pb_Vertex pb_Vertex = pb_Vertex.Average(vertices, indices);
Vector3 vector = pb_Math.Normal(vertices, face.indices);
int num = 0;
for (int i = 0; i < list.Count; i++)
{
int x2 = list[i].x;
list2[num].Add(vertices[x2]);
list3[num].Add(lookup[x2]);
if (indices.Contains(x2))
{
list4[num].Add(list2[num].Count);
list2[num].Add(pb_Vertex);
list3[num].Add(sharedIndexOffset);
num = (num + 1) % count;
list4[num].Add(list2[num].Count);
list2[num].Add(vertices[x2]);
list3[num].Add(lookup[x2]);
}
}
List<ConnectFaceRebuildData> list5 = new List<ConnectFaceRebuildData>();
for (int j = 0; j < list2.Count; j++)
{
if (list2[j].Count >= 3)
{
pb_FaceRebuildData pb_FaceRebuildData = pb_AppendPolygon.FaceWithVertices(list2[j], false);
pb_FaceRebuildData.sharedIndices = list3[j];
Vector3 vector2 = pb_Math.Normal(list2[j], pb_FaceRebuildData.face.indices);
if (Vector3.Dot(vector, vector2) < 0f)
{
pb_FaceRebuildData.face.ReverseIndices();
}
list5.Add(new ConnectFaceRebuildData(pb_FaceRebuildData, list4[j]));
}
}
return list5;
}
}
}
@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ProBuilder2.Common;
namespace ProBuilder2.MeshOperations
{
// Token: 0x0200000E RID: 14
public static class pb_DeleteVertices
{
// Token: 0x0600008C RID: 140 RVA: 0x0000B864 File Offset: 0x00009C64
public static int[] RemoveUnusedVertices(this pb_Object pb)
{
List<int> list = new List<int>();
HashSet<int> hashSet = new HashSet<int>(pb_Face.AllTriangles(pb.faces));
for (int i = 0; i < pb.vertices.Length; i++)
{
if (!hashSet.Contains(i))
{
list.Add(i);
}
}
pb.DeleteVerticesWithIndices(list);
return list.ToArray();
}
// Token: 0x0600008D RID: 141 RVA: 0x0000B8C4 File Offset: 0x00009CC4
public static void DeleteVerticesWithIndices(this pb_Object pb, IEnumerable<int> distInd)
{
if (distInd == null || distInd.Count<int>() < 1)
{
return;
}
pb_Vertex[] array = pb_Vertex.GetVertices(pb, null);
int num = array.Length;
int[] offset = new int[num];
List<int> sorted = new List<int>(distInd);
sorted.Sort();
array = array.SortedRemoveAt(sorted);
for (int i = 0; i < num; i++)
{
offset[i] = pbUtil.NearestIndexPriorToValue<int>(sorted, i) + 1;
}
foreach (pb_Face pb_Face in pb.faces)
{
int[] indices = pb_Face.indices;
for (int k = 0; k < indices.Length; k++)
{
indices[k] -= offset[indices[k]];
}
pb_Face.RebuildCaches();
}
IEnumerable<KeyValuePair<int, int>> enumerable = from x in pb.sharedIndices.ToDictionary()
where sorted.BinarySearch(x.Key) < 0
select x into y
select new KeyValuePair<int, int>(y.Key - offset[y.Key], y.Value);
IEnumerable<KeyValuePair<int, int>> enumerable2 = from x in pb.sharedIndicesUV.ToDictionary()
where sorted.BinarySearch(x.Key) < 0
select x into y
select new KeyValuePair<int, int>(y.Key - offset[y.Key], y.Value);
pb.SetVertices(array, false);
pb.SetSharedIndices(enumerable);
pb.SetSharedIndicesUV(enumerable2);
pb.ToMesh();
}
}
}
@@ -0,0 +1,293 @@
using System;
using System.Collections.Generic;
using ProBuilder2.Common;
using UnityEngine;
namespace ProBuilder2.MeshOperations
{
// Token: 0x0200000F RID: 15
public static class pb_Extrude
{
// Token: 0x0600008E RID: 142 RVA: 0x0000BAB2 File Offset: 0x00009EB2
public static bool Extrude(this pb_Object pb, pb_Face[] faces, ExtrudeMethod method, float distance)
{
if (method != ExtrudeMethod.IndividualFaces)
{
return pb_Extrude.ExtrudeAsGroups(pb, faces, method == ExtrudeMethod.FaceNormal, distance);
}
return pb_Extrude.ExtrudePerFace(pb, faces, distance);
}
// Token: 0x0600008F RID: 143 RVA: 0x0000BAD4 File Offset: 0x00009ED4
private static bool ExtrudePerFace(pb_Object pb, pb_Face[] faces, float distance)
{
if (faces == null || faces.Length < 1)
{
return false;
}
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
int num = pb.sharedIndices.Length;
int num2 = 0;
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
Dictionary<int, int> dictionary2 = pb.sharedIndicesUV.ToDictionary();
List<pb_Face> list2 = new List<pb_Face>(pb.faces);
Dictionary<int, int> dictionary3 = new Dictionary<int, int>();
foreach (pb_Face pb_Face in faces)
{
pb_Face.smoothingGroup = -1;
pb_Face.textureGroup = -1;
Vector3 vector = pb_Math.Normal(pb, pb_Face) * distance;
pb_Edge[] edges = pb_Face.edges;
dictionary3.Clear();
for (int j = 0; j < edges.Length; j++)
{
int count = list.Count;
int x = edges[j].x;
int y = edges[j].y;
if (!dictionary3.ContainsKey(x))
{
dictionary3.Add(x, dictionary[x]);
dictionary[x] = num + num2++;
}
if (!dictionary3.ContainsKey(y))
{
dictionary3.Add(y, dictionary[y]);
dictionary[y] = num + num2++;
}
dictionary.Add(count, dictionary3[x]);
dictionary.Add(count + 1, dictionary3[y]);
dictionary.Add(count + 2, dictionary[x]);
dictionary.Add(count + 3, dictionary[y]);
pb_Vertex pb_Vertex = new pb_Vertex(list[x]);
pb_Vertex pb_Vertex2 = new pb_Vertex(list[y]);
pb_Vertex.position += vector;
pb_Vertex2.position += vector;
list.Add(new pb_Vertex(list[x]));
list.Add(new pb_Vertex(list[y]));
list.Add(pb_Vertex);
list.Add(pb_Vertex2);
pb_Face pb_Face2 = new pb_Face(new int[]
{
count,
count + 1,
count + 2,
count + 1,
count + 3,
count + 2
}, pb_Face.material, new pb_UV(pb_Face.uv), pb_Face.smoothingGroup, -1, -1, false);
list2.Add(pb_Face2);
}
for (int k = 0; k < pb_Face.distinctIndices.Length; k++)
{
pb_Vertex pb_Vertex3 = list[pb_Face.distinctIndices[k]];
pb_Vertex3.position.x = pb_Vertex3.position.x + vector.x;
pb_Vertex pb_Vertex4 = list[pb_Face.distinctIndices[k]];
pb_Vertex4.position.y = pb_Vertex4.position.y + vector.y;
pb_Vertex pb_Vertex5 = list[pb_Face.distinctIndices[k]];
pb_Vertex5.position.z = pb_Vertex5.position.z + vector.z;
if (dictionary2 != null && dictionary2.ContainsKey(pb_Face.distinctIndices[k]))
{
dictionary2.Remove(pb_Face.distinctIndices[k]);
}
}
}
pb.SetVertices(list, false);
pb.SetFaces(list2.ToArray());
pb.SetSharedIndices(dictionary);
pb.SetSharedIndicesUV(dictionary2);
return true;
}
// Token: 0x06000090 RID: 144 RVA: 0x0000BE28 File Offset: 0x0000A228
private static bool ExtrudeAsGroups(pb_Object pb, pb_Face[] faces, bool compensateAngleVertexDistance, float distance)
{
if (faces == null || faces.Length < 1)
{
return false;
}
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
int num = pb.sharedIndices.Length;
int num2 = 0;
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
Dictionary<int, int> dictionary2 = pb.sharedIndicesUV.ToDictionary();
List<pb_Face> list2 = new List<pb_Face>(pb.faces);
Dictionary<int, int> dictionary3 = new Dictionary<int, int>();
Dictionary<int, int> dictionary4 = new Dictionary<int, int>();
Dictionary<int, int> dictionary5 = new Dictionary<int, int>();
Dictionary<int, pb_Tuple<Vector3, Vector3, List<int>>> dictionary6 = new Dictionary<int, pb_Tuple<Vector3, Vector3, List<int>>>();
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, faces, true, dictionary);
List<HashSet<pb_Face>> faceGroups = pb_Extrude.GetFaceGroups(wingedEdges);
foreach (HashSet<pb_Face> hashSet in faceGroups)
{
Dictionary<pb_EdgeLookup, pb_Face> perimeterEdges = pb_Extrude.GetPerimeterEdges(hashSet, dictionary);
dictionary4.Clear();
dictionary3.Clear();
foreach (KeyValuePair<pb_EdgeLookup, pb_Face> keyValuePair in perimeterEdges)
{
pb_EdgeLookup key = keyValuePair.Key;
pb_Face value = keyValuePair.Value;
int count = list.Count;
int x = key.local.x;
int y = key.local.y;
if (!dictionary3.ContainsKey(x))
{
dictionary3.Add(x, dictionary[x]);
int num3 = -1;
if (dictionary4.TryGetValue(dictionary[x], out num3))
{
dictionary[x] = num3;
}
else
{
num3 = num + num2++;
dictionary4.Add(dictionary[x], num3);
dictionary[x] = num3;
}
}
if (!dictionary3.ContainsKey(y))
{
dictionary3.Add(y, dictionary[y]);
int num4 = -1;
if (dictionary4.TryGetValue(dictionary[y], out num4))
{
dictionary[y] = num4;
}
else
{
num4 = num + num2++;
dictionary4.Add(dictionary[y], num4);
dictionary[y] = num4;
}
}
dictionary.Add(count, dictionary3[x]);
dictionary.Add(count + 1, dictionary3[y]);
dictionary.Add(count + 2, dictionary[x]);
dictionary.Add(count + 3, dictionary[y]);
dictionary5.Add(count + 2, x);
dictionary5.Add(count + 3, y);
list.Add(new pb_Vertex(list[x]));
list.Add(new pb_Vertex(list[y]));
list.Add(null);
list.Add(null);
pb_Face pb_Face = new pb_Face(new int[]
{
count,
count + 1,
count + 2,
count + 1,
count + 3,
count + 2
}, value.material, new pb_UV(value.uv), value.smoothingGroup, -1, -1, false);
list2.Add(pb_Face);
}
foreach (pb_Face pb_Face2 in hashSet)
{
pb_Face2.textureGroup = -1;
Vector3 vector = pb_Math.Normal(pb, pb_Face2);
for (int i = 0; i < pb_Face2.distinctIndices.Length; i++)
{
int num5 = pb_Face2.distinctIndices[i];
if (!dictionary3.ContainsKey(num5) && dictionary4.ContainsKey(dictionary[num5]))
{
dictionary[num5] = dictionary4[dictionary[num5]];
}
int num6 = dictionary[num5];
if (dictionary2 != null && dictionary2.ContainsKey(pb_Face2.distinctIndices[i]))
{
dictionary2.Remove(pb_Face2.distinctIndices[i]);
}
pb_Tuple<Vector3, Vector3, List<int>> pb_Tuple = null;
if (dictionary6.TryGetValue(num6, out pb_Tuple))
{
pb_Tuple<Vector3, Vector3, List<int>> pb_Tuple2 = pb_Tuple;
pb_Tuple2.Item1.x = pb_Tuple2.Item1.x + vector.x;
pb_Tuple<Vector3, Vector3, List<int>> pb_Tuple3 = pb_Tuple;
pb_Tuple3.Item1.y = pb_Tuple3.Item1.y + vector.y;
pb_Tuple<Vector3, Vector3, List<int>> pb_Tuple4 = pb_Tuple;
pb_Tuple4.Item1.z = pb_Tuple4.Item1.z + vector.z;
pb_Tuple.Item3.Add(num5);
}
else
{
dictionary6.Add(num6, new pb_Tuple<Vector3, Vector3, List<int>>(vector, vector, new List<int> { num5 }));
}
}
}
}
foreach (KeyValuePair<int, pb_Tuple<Vector3, Vector3, List<int>>> keyValuePair2 in dictionary6)
{
Vector3 vector2 = keyValuePair2.Value.Item1 / (float)keyValuePair2.Value.Item3.Count;
vector2.Normalize();
float num7 = ((!compensateAngleVertexDistance) ? 1f : pb_Math.Secant(Vector3.Angle(vector2, keyValuePair2.Value.Item2) * 0.017453292f));
vector2.x *= distance * num7;
vector2.y *= distance * num7;
vector2.z *= distance * num7;
foreach (int num8 in keyValuePair2.Value.Item3)
{
pb_Vertex pb_Vertex = list[num8];
pb_Vertex.position.x = pb_Vertex.position.x + vector2.x;
pb_Vertex pb_Vertex2 = list[num8];
pb_Vertex2.position.y = pb_Vertex2.position.y + vector2.y;
pb_Vertex pb_Vertex3 = list[num8];
pb_Vertex3.position.z = pb_Vertex3.position.z + vector2.z;
}
}
foreach (KeyValuePair<int, int> keyValuePair3 in dictionary5)
{
list[keyValuePair3.Key] = new pb_Vertex(list[keyValuePair3.Value]);
}
pb.SetVertices(list, false);
pb.SetFaces(list2.ToArray());
pb.SetSharedIndices(dictionary);
pb.SetSharedIndicesUV(dictionary2);
return true;
}
// Token: 0x06000091 RID: 145 RVA: 0x0000C528 File Offset: 0x0000A928
private static List<HashSet<pb_Face>> GetFaceGroups(List<pb_WingedEdge> wings)
{
HashSet<pb_Face> hashSet = new HashSet<pb_Face>();
List<HashSet<pb_Face>> list = new List<HashSet<pb_Face>>();
foreach (pb_WingedEdge pb_WingedEdge in wings)
{
if (hashSet.Add(pb_WingedEdge.face))
{
HashSet<pb_Face> hashSet2 = new HashSet<pb_Face> { pb_WingedEdge.face };
pb_GrowShrink.Flood(pb_WingedEdge, hashSet2);
foreach (pb_Face pb_Face in hashSet2)
{
hashSet.Add(pb_Face);
}
list.Add(hashSet2);
}
}
return list;
}
// Token: 0x06000092 RID: 146 RVA: 0x0000C60C File Offset: 0x0000AA0C
private static Dictionary<pb_EdgeLookup, pb_Face> GetPerimeterEdges(HashSet<pb_Face> faces, Dictionary<int, int> lookup)
{
Dictionary<pb_EdgeLookup, pb_Face> dictionary = new Dictionary<pb_EdgeLookup, pb_Face>();
HashSet<pb_EdgeLookup> hashSet = new HashSet<pb_EdgeLookup>();
foreach (pb_Face pb_Face in faces)
{
foreach (pb_Edge pb_Edge in pb_Face.edges)
{
pb_EdgeLookup pb_EdgeLookup = new pb_EdgeLookup(lookup[pb_Edge.x], lookup[pb_Edge.y], pb_Edge.x, pb_Edge.y);
if (!hashSet.Add(pb_EdgeLookup))
{
if (dictionary.ContainsKey(pb_EdgeLookup))
{
dictionary.Remove(pb_EdgeLookup);
}
}
else
{
dictionary.Add(pb_EdgeLookup, pb_Face);
}
}
}
return dictionary;
}
}
}
@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ProBuilder2.Common;
namespace ProBuilder2.MeshOperations
{
// Token: 0x02000010 RID: 16
public static class pb_Facetize
{
// Token: 0x06000093 RID: 147 RVA: 0x0000C6F4 File Offset: 0x0000AAF4
public static pb_ActionResult Facetize(this pb_Object pb, IList<pb_Face> faces, out pb_Face[] newFaces)
{
List<pb_Vertex> list = new List<pb_Vertex>(pb_Vertex.GetVertices(pb, null));
Dictionary<int, int> dictionary = pb.sharedIndices.ToDictionary();
List<pb_FaceRebuildData> list2 = new List<pb_FaceRebuildData>();
foreach (pb_Face pb_Face in faces)
{
List<pb_FaceRebuildData> list3 = pb_Facetize.BreakFaceIntoTris(pb_Face, list, dictionary);
list2.AddRange(list3);
}
pb_FaceRebuildData.Apply(list2, pb, list, null, dictionary, null);
pb.DeleteFaces(faces);
pb.ToMesh();
newFaces = list2.Select((pb_FaceRebuildData x) => x.face).ToArray<pb_Face>();
return new pb_ActionResult(Status.Success, string.Format("Triangulated {0} {1}", faces.Count, (faces.Count >= 2) ? "Faces" : "Face"));
}
// Token: 0x06000094 RID: 148 RVA: 0x0000C7F0 File Offset: 0x0000ABF0
private static List<pb_FaceRebuildData> BreakFaceIntoTris(pb_Face face, List<pb_Vertex> vertices, Dictionary<int, int> lookup)
{
int[] indices = face.indices;
int num = indices.Length;
List<pb_FaceRebuildData> list = new List<pb_FaceRebuildData>(num / 3);
for (int i = 0; i < num; i += 3)
{
pb_FaceRebuildData pb_FaceRebuildData = new pb_FaceRebuildData();
pb_FaceRebuildData.face = new pb_Face(face);
pb_FaceRebuildData.face.SetIndices(new int[] { 0, 1, 2 });
pb_FaceRebuildData.vertices = new List<pb_Vertex>
{
vertices[indices[i]],
vertices[indices[i + 1]],
vertices[indices[i + 2]]
};
pb_FaceRebuildData.sharedIndices = new List<int>
{
lookup[indices[i]],
lookup[indices[i + 1]],
lookup[indices[i + 2]]
};
list.Add(pb_FaceRebuildData);
}
return list;
}
}
}
@@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using ProBuilder2.Common;
using UnityEngine;
namespace ProBuilder2.MeshOperations
{
// Token: 0x02000011 RID: 17
public static class pb_GrowShrink
{
// Token: 0x06000096 RID: 150 RVA: 0x0000C8EC File Offset: 0x0000ACEC
public static HashSet<pb_Face> GrowSelection(pb_Object pb, IList<pb_Face> faces, float maxAngleDiff = -1f)
{
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, true);
HashSet<pb_Face> hashSet = new HashSet<pb_Face>(faces);
HashSet<pb_Face> hashSet2 = new HashSet<pb_Face>();
Vector3 vector = Vector3.zero;
bool flag = maxAngleDiff > 0f;
for (int i = 0; i < wingedEdges.Count; i++)
{
if (hashSet.Contains(wingedEdges[i].face))
{
if (flag)
{
vector = pb_Math.Normal(pb, wingedEdges[i].face);
}
pb_WingedEdgeEnumerator enumerator = wingedEdges[i].GetEnumerator();
try
{
while (enumerator.MoveNext())
{
pb_WingedEdge pb_WingedEdge = enumerator.Current;
if (pb_WingedEdge.opposite != null && !hashSet.Contains(pb_WingedEdge.opposite.face))
{
if (flag)
{
Vector3 vector2 = pb_Math.Normal(pb, pb_WingedEdge.opposite.face);
if (Vector3.Angle(vector, vector2) < maxAngleDiff)
{
hashSet2.Add(pb_WingedEdge.opposite.face);
}
}
else
{
hashSet2.Add(pb_WingedEdge.opposite.face);
}
}
}
}
finally
{
IDisposable disposable;
if ((disposable = enumerator as IDisposable) != null)
{
disposable.Dispose();
}
}
}
}
return hashSet2;
}
// Token: 0x06000097 RID: 151 RVA: 0x0000CA40 File Offset: 0x0000AE40
public static void Flood(pb_WingedEdge wing, HashSet<pb_Face> selection)
{
pb_GrowShrink.Flood(null, wing, pb_GrowShrink.Vector3_Zero, -1f, selection);
}
// Token: 0x06000098 RID: 152 RVA: 0x0000CA54 File Offset: 0x0000AE54
public static void Flood(pb_Object pb, pb_WingedEdge wing, Vector3 wingNrm, float maxAngle, HashSet<pb_Face> selection)
{
pb_WingedEdge pb_WingedEdge = wing;
do
{
pb_WingedEdge opposite = pb_WingedEdge.opposite;
if (opposite != null && !selection.Contains(opposite.face))
{
if (maxAngle > 0f)
{
Vector3 vector = pb_Math.Normal(pb, opposite.face);
if (Vector3.Angle(wingNrm, vector) < maxAngle && selection.Add(opposite.face))
{
pb_GrowShrink.Flood(pb, opposite, vector, maxAngle, selection);
}
}
else if (selection.Add(opposite.face))
{
pb_GrowShrink.Flood(pb, opposite, wingNrm, maxAngle, selection);
}
}
pb_WingedEdge = pb_WingedEdge.next;
}
while (pb_WingedEdge != wing);
}
// Token: 0x06000099 RID: 153 RVA: 0x0000CAF4 File Offset: 0x0000AEF4
public static HashSet<pb_Face> FloodSelection(pb_Object pb, IList<pb_Face> faces, float maxAngleDiff)
{
List<pb_WingedEdge> wingedEdges = pb_WingedEdge.GetWingedEdges(pb, true);
HashSet<pb_Face> hashSet = new HashSet<pb_Face>(faces);
HashSet<pb_Face> hashSet2 = new HashSet<pb_Face>();
for (int i = 0; i < wingedEdges.Count; i++)
{
if (!hashSet2.Contains(wingedEdges[i].face) && hashSet.Contains(wingedEdges[i].face))
{
hashSet2.Add(wingedEdges[i].face);
pb_GrowShrink.Flood(pb, wingedEdges[i], (maxAngleDiff <= 0f) ? pb_GrowShrink.Vector3_Zero : pb_Math.Normal(pb, wingedEdges[i].face), maxAngleDiff, hashSet2);
}
}
return hashSet2;
}
// Token: 0x0400002E RID: 46
private static readonly Vector3 Vector3_Zero = new Vector3(0f, 0f, 0f);
}
}
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using ProBuilder2.Common;
namespace ProBuilder2.MeshOperations
{
// Token: 0x02000012 RID: 18
public static class pb_Subdivide
{
// Token: 0x0600009B RID: 155 RVA: 0x0000CBC0 File Offset: 0x0000AFC0
public static pb_ActionResult Subdivide(this pb_Object pb)
{
pb_Face[] array;
return pb.Subdivide(pb.faces, out array);
}
// Token: 0x0600009C RID: 156 RVA: 0x0000CBDC File Offset: 0x0000AFDC
public static pb_ActionResult Subdivide(this pb_Object pb, IList<pb_Face> faces, out pb_Face[] subdividedFaces)
{
return pb.Connect(faces, out subdividedFaces);
}
}
}
@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Poly2Tri;
using ProBuilder2.Common;
using UnityEngine;
namespace ProBuilder2.MeshOperations
{
// Token: 0x02000013 RID: 19
public static class pb_Triangulation
{
// Token: 0x0600009D RID: 157 RVA: 0x0000CBF4 File Offset: 0x0000AFF4
public static bool SortAndTriangulate(IList<Vector2> points, out List<int> indices, bool convex = false)
{
IList<Vector2> list = pb_Projection.Sort(points, SortMethod.CounterClockwise);
Dictionary<int, int> dictionary = new Dictionary<int, int>();
for (int i = 0; i < list.Count; i++)
{
dictionary.Add(i, points.IndexOf(list[i]));
}
if (!pb_Triangulation.Triangulate(list, out indices, convex))
{
return false;
}
for (int j = 0; j < indices.Count; j++)
{
indices[j] = dictionary[indices[j]];
}
return true;
}
// Token: 0x0600009E RID: 158 RVA: 0x0000CC78 File Offset: 0x0000B078
public static bool TriangulateVertices(IList<pb_Vertex> vertices, out List<int> triangles, bool unordered = true, bool convex = false)
{
Vector3[] array = new Vector3[vertices.Count];
for (int i = 0; i < vertices.Count; i++)
{
array[i] = vertices[i].position;
}
return pb_Triangulation.TriangulateVertices(array, out triangles, unordered, convex);
}
// Token: 0x0600009F RID: 159 RVA: 0x0000CCCC File Offset: 0x0000B0CC
public static bool TriangulateVertices(Vector3[] vertices, out List<int> triangles, bool unordered = true, bool convex = false)
{
triangles = null;
int num = ((vertices != null) ? vertices.Length : 0);
if (num < 3)
{
return false;
}
if (num == 3)
{
triangles = new List<int> { 0, 1, 2 };
return true;
}
Vector3 normal = pb_Projection.FindBestPlane(vertices, null).normal;
Vector2[] array = pb_Projection.PlanarProject(vertices, normal);
if (unordered)
{
return pb_Triangulation.SortAndTriangulate(array, out triangles, convex);
}
return pb_Triangulation.Triangulate(array, out triangles, convex);
}
// Token: 0x060000A0 RID: 160 RVA: 0x0000CD50 File Offset: 0x0000B150
public static bool Triangulate(IList<Vector2> points, out List<int> indices, bool convex = false)
{
indices = new List<int>();
int index = 0;
Triangulatable triangulatable2;
if (convex)
{
Triangulatable triangulatable = new PointSet(points.Select((Vector2 x) => new TriangulationPoint((double)x.x, (double)x.y, index++)).ToList<TriangulationPoint>());
triangulatable2 = triangulatable;
}
else
{
triangulatable2 = new Polygon(points.Select((Vector2 x) => new PolygonPoint((double)x.x, (double)x.y, index++)));
}
Triangulatable triangulatable3 = triangulatable2;
P2T.Triangulate(TriangulationAlgorithm.DTSweep, triangulatable3);
foreach (DelaunayTriangle delaunayTriangle in triangulatable3.Triangles)
{
if (delaunayTriangle.Points[0].Index < 0 || delaunayTriangle.Points[1].Index < 0 || delaunayTriangle.Points[2].Index < 0)
{
pb_Log.Warning("Triangulation failed - additional vertices were inserted.");
return false;
}
indices.Add(delaunayTriangle.Points[0].Index);
indices.Add(delaunayTriangle.Points[1].Index);
indices.Add(delaunayTriangle.Points[2].Index);
}
WindingOrder windingOrder = pbTriangleOps.GetWindingOrder(points);
if (pbTriangleOps.GetWindingOrder(new Vector2[]
{
points[indices[0]],
points[indices[1]],
points[indices[2]]
}) != windingOrder)
{
indices.Reverse();
}
return true;
}
}
}
@@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.Linq;
using KdTree;
using KdTree.Math;
using ProBuilder2.Common;
using UnityEngine;
namespace ProBuilder2.MeshOperations
{
// Token: 0x02000014 RID: 20
public static class pb_WeldVertices
{
// Token: 0x060000A1 RID: 161 RVA: 0x0000CF88 File Offset: 0x0000B388
public static pb_ActionResult WeldVertices(this pb_Object pb, int[] indices, float neighborRadius, out int[] welds)
{
pb_Vertex[] vertices = pb_Vertex.GetVertices(pb, null);
pb_IntArray[] sharedIndices = pb.sharedIndices;
Dictionary<int, int> dictionary = sharedIndices.ToDictionary();
HashSet<int> commonIndices = pb_IntArrayUtility.GetCommonIndices(dictionary, indices);
int count = commonIndices.Count;
int num = Math.Min(32, commonIndices.Count<int>());
KdTree<float, int> kdTree = new KdTree<float, int>(3, new FloatMath(), AddDuplicateBehavior.Collect);
foreach (int num2 in commonIndices)
{
Vector3 position = vertices[sharedIndices[num2][0]].position;
kdTree.Add(new float[] { position.x, position.y, position.z }, num2);
}
float[] array = new float[3];
Dictionary<int, int> dictionary2 = new Dictionary<int, int>();
Dictionary<int, Vector3> dictionary3 = new Dictionary<int, Vector3>();
int num3 = sharedIndices.Length;
foreach (int num4 in commonIndices)
{
if (!dictionary2.ContainsKey(num4))
{
Vector3 position2 = vertices[sharedIndices[num4][0]].position;
array[0] = position2.x;
array[1] = position2.y;
array[2] = position2.z;
KdTreeNode<float, int>[] array2 = kdTree.RadialSearch(array, neighborRadius, num);
if (num < count && array2.Length >= num)
{
array2 = kdTree.RadialSearch(array, neighborRadius, count);
num = Math.Min(count, array2.Length + array2.Length / 2);
}
Vector3 zero = Vector3.zero;
float num5 = 0f;
for (int i = 0; i < array2.Length; i++)
{
int value = array2[i].Value;
if (!dictionary2.ContainsKey(value))
{
zero.x += array2[i].Point[0];
zero.y += array2[i].Point[1];
zero.z += array2[i].Point[2];
dictionary2.Add(value, num3);
num5 += 1f;
if (array2[i].Duplicates != null)
{
for (int j = 0; j < array2[i].Duplicates.Count; j++)
{
dictionary2.Add(array2[i].Duplicates[j], num3);
}
}
}
}
zero.x /= num5;
zero.y /= num5;
zero.z /= num5;
dictionary3.Add(num3, zero);
num3++;
}
}
welds = new int[dictionary2.Count];
int num6 = 0;
foreach (KeyValuePair<int, int> keyValuePair in dictionary2)
{
int[] array3 = sharedIndices[keyValuePair.Key];
welds[num6++] = array3[0];
for (int k = 0; k < array3.Length; k++)
{
dictionary[array3[k]] = keyValuePair.Value;
vertices[array3[k]].position = dictionary3[keyValuePair.Value];
}
}
pb.SetSharedIndices(dictionary);
pb.SetVertices(vertices, false);
pb.ToMesh();
return new pb_ActionResult(Status.Success, "Weld Vertices");
}
}
}