Files
2026-06-04 11:42:34 +02:00

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
};
}
}