353 lines
14 KiB
C#
353 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace ProBuilder2.Common
|
|
{
|
|
// Token: 0x0200003C RID: 60
|
|
public static class pb_SelectionPicker
|
|
{
|
|
// Token: 0x17000034 RID: 52
|
|
// (get) Token: 0x060001EC RID: 492 RVA: 0x00018520 File Offset: 0x00016920
|
|
private static RenderTextureFormat renderTextureFormat
|
|
{
|
|
get
|
|
{
|
|
if (pb_SelectionPicker.m_Initialized)
|
|
{
|
|
return pb_SelectionPicker.m_RenderTextureFormat;
|
|
}
|
|
pb_SelectionPicker.m_Initialized = true;
|
|
for (int i = 0; i < pb_SelectionPicker.m_PreferredFormats.Length; i++)
|
|
{
|
|
if (SystemInfo.SupportsRenderTextureFormat(pb_SelectionPicker.m_PreferredFormats[i]))
|
|
{
|
|
pb_SelectionPicker.m_RenderTextureFormat = pb_SelectionPicker.m_PreferredFormats[i];
|
|
break;
|
|
}
|
|
}
|
|
return pb_SelectionPicker.m_RenderTextureFormat;
|
|
}
|
|
}
|
|
|
|
// Token: 0x17000035 RID: 53
|
|
// (get) Token: 0x060001ED RID: 493 RVA: 0x00018582 File Offset: 0x00016982
|
|
private static TextureFormat textureFormat
|
|
{
|
|
get
|
|
{
|
|
return TextureFormat.ARGB32;
|
|
}
|
|
}
|
|
|
|
// Token: 0x060001EE RID: 494 RVA: 0x00018588 File Offset: 0x00016988
|
|
public static Dictionary<pb_Object, HashSet<pb_Face>> PickFacesInRect(Camera camera, Rect pickerRect, IEnumerable<pb_Object> selection, int renderTextureWidth = -1, int renderTextureHeight = -1)
|
|
{
|
|
Dictionary<uint, pb_Tuple<pb_Object, pb_Face>> dictionary;
|
|
Texture2D texture2D = pb_SelectionPicker.RenderSelectionPickerTexture(camera, selection, out dictionary, renderTextureWidth, renderTextureHeight);
|
|
Color32[] pixels = texture2D.GetPixels32();
|
|
int num = Math.Max(0, Mathf.FloorToInt(pickerRect.x));
|
|
int num2 = Math.Max(0, Mathf.FloorToInt((float)texture2D.height - pickerRect.y - pickerRect.height));
|
|
int width = texture2D.width;
|
|
int height = texture2D.height;
|
|
int num3 = Mathf.FloorToInt(pickerRect.width);
|
|
int num4 = Mathf.FloorToInt(pickerRect.height);
|
|
global::UnityEngine.Object.DestroyImmediate(texture2D);
|
|
Dictionary<pb_Object, HashSet<pb_Face>> dictionary2 = new Dictionary<pb_Object, HashSet<pb_Face>>();
|
|
HashSet<pb_Face> hashSet = null;
|
|
HashSet<uint> hashSet2 = new HashSet<uint>();
|
|
for (int i = num2; i < Math.Min(num2 + num4, height); i++)
|
|
{
|
|
for (int j = num; j < Math.Min(num + num3, width); j++)
|
|
{
|
|
uint num5 = pb_SelectionPicker.DecodeRGBA(pixels[i * width + j]);
|
|
pb_Tuple<pb_Object, pb_Face> pb_Tuple;
|
|
if (hashSet2.Add(num5) && dictionary.TryGetValue(num5, out pb_Tuple))
|
|
{
|
|
if (dictionary2.TryGetValue(pb_Tuple.Item1, out hashSet))
|
|
{
|
|
hashSet.Add(pb_Tuple.Item2);
|
|
}
|
|
else
|
|
{
|
|
dictionary2.Add(pb_Tuple.Item1, new HashSet<pb_Face> { pb_Tuple.Item2 });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return dictionary2;
|
|
}
|
|
|
|
// Token: 0x060001EF RID: 495 RVA: 0x000186F0 File Offset: 0x00016AF0
|
|
public static Dictionary<pb_Object, HashSet<int>> PickVerticesInRect(Camera camera, Rect pickerRect, IEnumerable<pb_Object> selection, int renderTextureWidth = -1, int renderTextureHeight = -1)
|
|
{
|
|
Dictionary<pb_Object, HashSet<int>> dictionary = new Dictionary<pb_Object, HashSet<int>>();
|
|
Dictionary<uint, pb_Tuple<pb_Object, int>> dictionary2;
|
|
Texture2D texture2D = pb_SelectionPicker.RenderSelectionPickerTexture(camera, selection, out dictionary2, renderTextureWidth, renderTextureHeight);
|
|
Color32[] pixels = texture2D.GetPixels32();
|
|
int num = Math.Max(0, Mathf.FloorToInt(pickerRect.x));
|
|
int num2 = Math.Max(0, Mathf.FloorToInt((float)texture2D.height - pickerRect.y - pickerRect.height));
|
|
int width = texture2D.width;
|
|
int height = texture2D.height;
|
|
int num3 = Mathf.FloorToInt(pickerRect.width);
|
|
int num4 = Mathf.FloorToInt(pickerRect.height);
|
|
global::UnityEngine.Object.DestroyImmediate(texture2D);
|
|
HashSet<int> hashSet = null;
|
|
HashSet<uint> hashSet2 = new HashSet<uint>();
|
|
for (int i = num2; i < Math.Min(num2 + num4, height); i++)
|
|
{
|
|
for (int j = num; j < Math.Min(num + num3, width); j++)
|
|
{
|
|
uint num5 = pb_SelectionPicker.DecodeRGBA(pixels[i * width + j]);
|
|
pb_Tuple<pb_Object, int> pb_Tuple;
|
|
if (hashSet2.Add(num5) && dictionary2.TryGetValue(num5, out pb_Tuple))
|
|
{
|
|
if (dictionary.TryGetValue(pb_Tuple.Item1, out hashSet))
|
|
{
|
|
hashSet.Add(pb_Tuple.Item2);
|
|
}
|
|
else
|
|
{
|
|
dictionary.Add(pb_Tuple.Item1, new HashSet<int> { pb_Tuple.Item2 });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return dictionary;
|
|
}
|
|
|
|
// Token: 0x060001F0 RID: 496 RVA: 0x00018854 File Offset: 0x00016C54
|
|
public static Texture2D RenderSelectionPickerTexture(Camera camera, IEnumerable<pb_Object> selection, out Dictionary<uint, pb_Tuple<pb_Object, pb_Face>> map, int width = -1, int height = -1)
|
|
{
|
|
List<GameObject> list = pb_SelectionPicker.GenerateFaceDepthTestMeshes(selection, out map);
|
|
Texture2D texture2D = pb_SelectionPicker.RenderWithReplacementShader(camera, pb_Constant.SelectionPickerShader, "ProBuilderPicker", width, height);
|
|
foreach (GameObject gameObject in list)
|
|
{
|
|
global::UnityEngine.Object.DestroyImmediate(gameObject.GetComponent<MeshFilter>().sharedMesh);
|
|
global::UnityEngine.Object.DestroyImmediate(gameObject);
|
|
}
|
|
return texture2D;
|
|
}
|
|
|
|
// Token: 0x060001F1 RID: 497 RVA: 0x000188D8 File Offset: 0x00016CD8
|
|
public static Texture2D RenderSelectionPickerTexture(Camera camera, IEnumerable<pb_Object> selection, out Dictionary<uint, pb_Tuple<pb_Object, int>> map, int width = -1, int height = -1)
|
|
{
|
|
List<GameObject> list = pb_SelectionPicker.GenerateVertexDepthTestMeshes(selection, out map);
|
|
Texture2D texture2D = pb_SelectionPicker.RenderWithReplacementShader(camera, pb_Constant.SelectionPickerShader, "ProBuilderPicker", width, height);
|
|
foreach (GameObject gameObject in list)
|
|
{
|
|
global::UnityEngine.Object.DestroyImmediate(gameObject.GetComponent<MeshFilter>().sharedMesh);
|
|
global::UnityEngine.Object.DestroyImmediate(gameObject);
|
|
}
|
|
return texture2D;
|
|
}
|
|
|
|
// Token: 0x060001F2 RID: 498 RVA: 0x0001895C File Offset: 0x00016D5C
|
|
public static List<GameObject> GenerateFaceDepthTestMeshes(IEnumerable<pb_Object> selection, out Dictionary<uint, pb_Tuple<pb_Object, pb_Face>> map)
|
|
{
|
|
List<GameObject> list = new List<GameObject>();
|
|
map = new Dictionary<uint, pb_Tuple<pb_Object, pb_Face>>();
|
|
uint num = 0U;
|
|
foreach (pb_Object pb_Object in selection)
|
|
{
|
|
GameObject gameObject = new GameObject();
|
|
gameObject.name = pb_Object.name + " (Face Depth Test)";
|
|
gameObject.transform.position = pb_Object.transform.position;
|
|
gameObject.transform.localRotation = pb_Object.transform.localRotation;
|
|
gameObject.transform.localScale = pb_Object.transform.localScale;
|
|
Mesh mesh = new Mesh();
|
|
mesh.vertices = pb_Object.vertices;
|
|
mesh.triangles = pb_Object.faces.SelectMany((pb_Face x) => x.indices).ToArray<int>();
|
|
Color32[] array = new Color32[mesh.vertexCount];
|
|
foreach (pb_Face pb_Face in pb_Object.faces)
|
|
{
|
|
Color32 color = pb_SelectionPicker.EncodeRGBA(num++);
|
|
map.Add(pb_SelectionPicker.DecodeRGBA(color), new pb_Tuple<pb_Object, pb_Face>(pb_Object, pb_Face));
|
|
for (int j = 0; j < pb_Face.distinctIndices.Length; j++)
|
|
{
|
|
array[pb_Face.distinctIndices[j]] = color;
|
|
}
|
|
}
|
|
mesh.colors32 = array;
|
|
try
|
|
{
|
|
gameObject.AddComponent<MeshFilter>().sharedMesh = mesh;
|
|
gameObject.AddComponent<MeshRenderer>().sharedMaterial = pb_Constant.FacePickerMaterial;
|
|
}
|
|
catch
|
|
{
|
|
Debug.LogWarning("Could not find shader `pb_FacePicker.shader`. Please re-import ProBuilder to fix!");
|
|
}
|
|
list.Add(gameObject);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
// Token: 0x060001F3 RID: 499 RVA: 0x00018B5C File Offset: 0x00016F5C
|
|
private static List<GameObject> GenerateVertexDepthTestMeshes(IEnumerable<pb_Object> selection, out Dictionary<uint, pb_Tuple<pb_Object, int>> map)
|
|
{
|
|
List<GameObject> list = new List<GameObject>();
|
|
map = new Dictionary<uint, pb_Tuple<pb_Object, int>>();
|
|
Color32 color = new Color32(0, 0, 0, byte.MaxValue);
|
|
uint num = 2U;
|
|
foreach (pb_Object pb_Object in selection)
|
|
{
|
|
GameObject gameObject = pbUtil.EmptyGameObjectWithTransform(pb_Object.transform);
|
|
gameObject.name = pb_Object.name + " (Depth Mask)";
|
|
Mesh mesh = new Mesh();
|
|
mesh.vertices = pb_Object.vertices;
|
|
mesh.triangles = pb_Object.faces.SelectMany((pb_Face x) => x.indices).ToArray<int>();
|
|
mesh.colors32 = pbUtil.Fill<Color32>(color, pb_Object.vertexCount);
|
|
gameObject.AddComponent<MeshFilter>().sharedMesh = mesh;
|
|
gameObject.AddComponent<MeshRenderer>().sharedMaterial = pb_Constant.FacePickerMaterial;
|
|
list.Add(gameObject);
|
|
GameObject gameObject2 = pbUtil.EmptyGameObjectWithTransform(pb_Object.transform);
|
|
gameObject2.name = pb_Object.name + " (Vertex Billboards)";
|
|
gameObject2.AddComponent<MeshFilter>().sharedMesh = pb_SelectionPicker.BuildVertexMesh(pb_Object, map, ref num);
|
|
gameObject2.AddComponent<MeshRenderer>().sharedMaterial = pb_Constant.VertexPickerMaterial;
|
|
list.Add(gameObject2);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
// Token: 0x060001F4 RID: 500 RVA: 0x00018CD4 File Offset: 0x000170D4
|
|
private static Mesh BuildVertexMesh(pb_Object pb, Dictionary<uint, pb_Tuple<pb_Object, int>> map, ref uint index)
|
|
{
|
|
int num = Math.Min(pb.sharedIndices.Length, 16382);
|
|
Vector3[] array = new Vector3[num * 4];
|
|
Vector2[] array2 = new Vector2[num * 4];
|
|
Vector2[] array3 = new Vector2[num * 4];
|
|
Color[] array4 = new Color[num * 4];
|
|
int[] array5 = new int[num * 6];
|
|
int num2 = 0;
|
|
int num3 = 0;
|
|
Vector3 up = Vector3.up;
|
|
Vector3 right = Vector3.right;
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
Vector3 vector = pb.vertices[pb.sharedIndices[i][0]];
|
|
array[num3] = vector;
|
|
array[num3 + 1] = vector;
|
|
array[num3 + 2] = vector;
|
|
array[num3 + 3] = vector;
|
|
array2[num3] = Vector3.zero;
|
|
array2[num3 + 1] = Vector3.right;
|
|
array2[num3 + 2] = Vector3.up;
|
|
array2[num3 + 3] = Vector3.one;
|
|
array3[num3] = -up - right;
|
|
array3[num3 + 1] = -up + right;
|
|
array3[num3 + 2] = up - right;
|
|
array3[num3 + 3] = up + right;
|
|
array5[num2] = num3;
|
|
array5[num2 + 1] = num3 + 1;
|
|
array5[num2 + 2] = num3 + 2;
|
|
array5[num2 + 3] = num3 + 1;
|
|
array5[num2 + 4] = num3 + 3;
|
|
array5[num2 + 5] = num3 + 2;
|
|
Color32 color = pb_SelectionPicker.EncodeRGBA(index);
|
|
uint num4;
|
|
index = (num4 = index) + 1U;
|
|
map.Add(num4, new pb_Tuple<pb_Object, int>(pb, i));
|
|
array4[num3] = color;
|
|
array4[num3 + 1] = color;
|
|
array4[num3 + 2] = color;
|
|
array4[num3 + 3] = color;
|
|
num3 += 4;
|
|
num2 += 6;
|
|
}
|
|
return new Mesh
|
|
{
|
|
name = "Vertex Billboard",
|
|
vertices = array,
|
|
uv = array2,
|
|
uv2 = array3,
|
|
colors = array4,
|
|
triangles = array5
|
|
};
|
|
}
|
|
|
|
// Token: 0x060001F5 RID: 501 RVA: 0x00018F94 File Offset: 0x00017394
|
|
public static uint DecodeRGBA(Color32 color)
|
|
{
|
|
uint r = (uint)color.r;
|
|
uint g = (uint)color.g;
|
|
uint b = (uint)color.b;
|
|
if (BitConverter.IsLittleEndian)
|
|
{
|
|
return (r << 16) | (g << 8) | b;
|
|
}
|
|
return (r << 24) | (g << 16) | (b << 8);
|
|
}
|
|
|
|
// Token: 0x060001F6 RID: 502 RVA: 0x00018FDC File Offset: 0x000173DC
|
|
public static Color32 EncodeRGBA(uint hash)
|
|
{
|
|
if (BitConverter.IsLittleEndian)
|
|
{
|
|
return new Color32((byte)((hash >> 16) & 255U), (byte)((hash >> 8) & 255U), (byte)(hash & 255U), byte.MaxValue);
|
|
}
|
|
return new Color32((byte)((hash >> 24) & 255U), (byte)((hash >> 16) & 255U), (byte)((hash >> 8) & 255U), byte.MaxValue);
|
|
}
|
|
|
|
// Token: 0x060001F7 RID: 503 RVA: 0x00019048 File Offset: 0x00017448
|
|
private static Texture2D RenderWithReplacementShader(Camera camera, Shader shader, string tag, int width = -1, int height = -1)
|
|
{
|
|
bool flag = width < 0 || height < 0;
|
|
int num = ((!flag) ? width : ((int)camera.pixelRect.width));
|
|
int num2 = ((!flag) ? height : ((int)camera.pixelRect.height));
|
|
GameObject gameObject = new GameObject();
|
|
Camera camera2 = gameObject.AddComponent<Camera>();
|
|
camera2.CopyFrom(camera);
|
|
camera2.renderingPath = RenderingPath.Forward;
|
|
camera2.enabled = false;
|
|
camera2.clearFlags = CameraClearFlags.Color;
|
|
camera2.backgroundColor = Color.white;
|
|
camera2.allowHDR = false;
|
|
camera2.allowMSAA = false;
|
|
camera2.forceIntoRenderTexture = true;
|
|
RenderTextureDescriptor renderTextureDescriptor = new RenderTextureDescriptor
|
|
{
|
|
width = num,
|
|
height = num2,
|
|
colorFormat = pb_SelectionPicker.renderTextureFormat,
|
|
autoGenerateMips = false,
|
|
depthBufferBits = 16,
|
|
dimension = TextureDimension.Tex2D,
|
|
enableRandomWrite = false,
|
|
memoryless = RenderTextureMemoryless.None,
|
|
sRGB = false,
|
|
useMipMap = false,
|
|
volumeDepth = 1,
|
|
msaaSamples = 1
|
|
};
|
|
RenderTexture temporary = RenderTexture.GetTemporary(renderTextureDescriptor);
|
|
RenderTexture active = RenderTexture.active;
|
|
camera2.targetTexture = temporary;
|
|
RenderTexture.active = temporary;
|
|
camera2.RenderWithShader(shader, tag);
|
|
Texture2D texture2D = new Texture2D(num, num2, pb_SelectionPicker.textureFormat, false, false);
|
|
texture2D.ReadPixels(new Rect(0f, 0f, (float)num, (float)num2), 0, 0);
|
|
texture2D.Apply();
|
|
RenderTexture.active = active;
|
|
RenderTexture.ReleaseTemporary(temporary);
|
|
global::UnityEngine.Object.DestroyImmediate(gameObject);
|
|
return texture2D;
|
|
}
|
|
|
|
// Token: 0x0400016F RID: 367
|
|
private static bool m_Initialized = false;
|
|
|
|
// Token: 0x04000170 RID: 368
|
|
private static RenderTextureFormat m_RenderTextureFormat = RenderTextureFormat.Default;
|
|
|
|
// Token: 0x04000171 RID: 369
|
|
private static RenderTextureFormat[] m_PreferredFormats = new RenderTextureFormat[]
|
|
{
|
|
RenderTextureFormat.ARGB32,
|
|
RenderTextureFormat.ARGBFloat
|
|
};
|
|
}
|
|
}
|