Files
2026-06-01 17:19:55 +02:00

946 lines
27 KiB
C#

using UnityEngine;
using UnityEngine.Rendering;
namespace BlockSpace.Voxels
{
[DisallowMultipleComponent]
public sealed class VoxelGroup : MonoBehaviour
{
private static readonly int BaseColorId = Shader.PropertyToID("_BaseColor");
private static readonly int ColorId = Shader.PropertyToID("_Color");
private static readonly int TintColorId = Shader.PropertyToID("_TintColor");
private static readonly int EmissionColorId = Shader.PropertyToID("_EmissionColor");
private static readonly int EmissiveColorId = Shader.PropertyToID("_EmissiveColor");
private static readonly Color SelectedTintColor = new Color(0.86f, 1f, 0.88f, 1f);
public ushort id;
[HideInInspector]
public int zoneID = -1;
public Vector3Int position;
public byte packedRotation;
public Vector3Int size;
public byte[] voxels;
[HideInInspector]
public MeshFilter meshFilter;
[HideInInspector]
public MeshRenderer meshRenderer;
[HideInInspector]
public MeshCollider meshCollider;
[HideInInspector]
public bool dirtyMesh = true;
[HideInInspector]
public bool dirtyCollider = true;
[SerializeField]
private bool creatorMode;
[SerializeField]
private bool useLocalGridTransform;
[SerializeField]
private float voxelSizeScale = 1f;
private VoxelGroupManager owner;
private Mesh renderMesh;
private Mesh renderMeshUnlit;
private Mesh renderMeshTransparent;
private Mesh renderMeshInvisible;
private Mesh collisionMesh;
private MeshFilter unlitMeshFilter;
private MeshRenderer unlitMeshRenderer;
private MeshFilter transparentMeshFilter;
private MeshRenderer transparentMeshRenderer;
private MeshFilter invisibleMeshFilter;
private MeshRenderer invisibleMeshRenderer;
private bool useGreedyRenderMeshing = true;
private bool allowColliderGeneration = true;
private MaterialPropertyBlock propertyBlock;
public bool IsSelected { get; private set; }
internal bool UsesLocalGridTransform => useLocalGridTransform;
internal float CurrentVoxelSize => ((owner != null) ? owner.VoxelSize : 0.125f) * Mathf.Max(0.001f, voxelSizeScale);
public void Initialize(VoxelGroupManager manager, ushort groupId, Vector3Int gridPosition, byte rotation, Vector3Int groupSize, byte[] voxelData, bool queueInitialRebuild = true)
{
owner = manager;
id = groupId;
position = gridPosition;
packedRotation = rotation;
size = groupSize;
voxels = voxelData;
creatorMode = owner != null && owner.CreatorMode;
EnsureComponents();
ApplyGridTransform();
BindMaterials((owner != null) ? owner.SharedMaterials : null);
if (queueInitialRebuild)
{
MarkDirty(mesh: true, collider: true);
return;
}
dirtyMesh = false;
dirtyCollider = false;
meshRenderer.enabled = false;
meshCollider.sharedMesh = null;
meshCollider.enabled = false;
}
public void SetVoxel(int x, int y, int z, byte value)
{
if (IsInBounds(x, y, z) && voxels != null)
{
int flatIndex = GetFlatIndex(x, y, z);
if (voxels[flatIndex] != value)
{
voxels[flatIndex] = value;
MarkDirty(mesh: true, collider: true);
}
}
}
public byte GetVoxel(int x, int y, int z)
{
if (!IsInBounds(x, y, z) || voxels == null)
{
return 0;
}
return voxels[GetFlatIndex(x, y, z)];
}
public Bounds GetWorldBounds()
{
if (size.x <= 0 || size.y <= 0 || size.z <= 0)
{
return new Bounds(base.transform.position, Vector3.zero);
}
Vector3 vector = new Vector3(size.x, size.y, size.z) * CurrentVoxelSize;
Vector3[] array = new Vector3[8]
{
base.transform.TransformPoint(new Vector3(0f, 0f, 0f)),
base.transform.TransformPoint(new Vector3(vector.x, 0f, 0f)),
base.transform.TransformPoint(new Vector3(0f, vector.y, 0f)),
base.transform.TransformPoint(new Vector3(0f, 0f, vector.z)),
base.transform.TransformPoint(new Vector3(vector.x, vector.y, 0f)),
base.transform.TransformPoint(new Vector3(vector.x, 0f, vector.z)),
base.transform.TransformPoint(new Vector3(0f, vector.y, vector.z)),
base.transform.TransformPoint(new Vector3(vector.x, vector.y, vector.z))
};
Bounds result = new Bounds(array[0], Vector3.zero);
for (int i = 1; i < array.Length; i++)
{
result.Encapsulate(array[i]);
}
return result;
}
public void RebuildMesh()
{
EnsureComponents();
if (renderMesh == null)
{
renderMesh = new Mesh
{
name = $"VoxelGroup_Render_{id}"
};
renderMesh.indexFormat = IndexFormat.UInt32;
}
if (renderMeshUnlit == null)
{
renderMeshUnlit = new Mesh
{
name = $"VoxelGroup_RenderUnlit_{id}"
};
renderMeshUnlit.indexFormat = IndexFormat.UInt32;
}
if (renderMeshTransparent == null)
{
renderMeshTransparent = new Mesh
{
name = $"VoxelGroup_RenderTransparent_{id}"
};
renderMeshTransparent.indexFormat = IndexFormat.UInt32;
}
if (renderMeshInvisible == null)
{
renderMeshInvisible = new Mesh
{
name = $"VoxelGroup_RenderInvisible_{id}"
};
renderMeshInvisible.indexFormat = IndexFormat.UInt32;
}
bool flag = owner != null && owner.CreatorMode;
GreedyMesher.MeshData meshData = (useGreedyRenderMeshing ? GreedyMesher.BuildRenderMesh(size, voxels, flag, CurrentVoxelSize) : GreedyMesher.BuildCulledRenderMesh(size, voxels, flag, CurrentVoxelSize));
ApplyMeshSubmesh(renderMesh, meshData, 0, applyColors: true);
meshFilter.sharedMesh = renderMesh;
meshRenderer.enabled = meshData.SubmeshTriangles.Length != 0 && meshData.SubmeshTriangles[0].Count > 0;
ApplyMeshSubmesh(renderMeshUnlit, meshData, 1, applyColors: true);
unlitMeshFilter.sharedMesh = renderMeshUnlit;
unlitMeshRenderer.enabled = meshData.SubmeshTriangles.Length > 1 && meshData.SubmeshTriangles[1].Count > 0;
ApplyMeshSubmesh(renderMeshTransparent, meshData, 2, applyColors: true);
transparentMeshFilter.sharedMesh = renderMeshTransparent;
transparentMeshRenderer.enabled = meshData.SubmeshTriangles.Length > 2 && meshData.SubmeshTriangles[2].Count > 0;
ApplyMeshSubmesh(renderMeshInvisible, meshData, 3, applyColors: true);
invisibleMeshFilter.sharedMesh = renderMeshInvisible;
invisibleMeshRenderer.enabled = meshData.SubmeshTriangles.Length > 3 && meshData.SubmeshTriangles[3].Count > 0;
dirtyMesh = false;
}
public void RebuildCollider()
{
EnsureComponents();
if (!allowColliderGeneration)
{
meshCollider.sharedMesh = null;
meshCollider.enabled = false;
dirtyCollider = false;
return;
}
if (collisionMesh == null)
{
collisionMesh = new Mesh
{
name = $"VoxelGroup_Collider_{id}"
};
collisionMesh.indexFormat = IndexFormat.UInt32;
}
GreedyMesher.MeshData meshData = GreedyMesher.BuildColliderMesh(size, voxels, CurrentVoxelSize);
ApplyMeshSubmesh(collisionMesh, meshData, 0, applyColors: false);
meshCollider.sharedMesh = null;
meshCollider.sharedMesh = ((collisionMesh.vertexCount > 0) ? collisionMesh : null);
meshCollider.enabled = collisionMesh.vertexCount > 0;
dirtyCollider = false;
}
public bool EraseSphere(Vector3 worldCenter, float radius, bool markMeshDirty = true, bool markColliderDirty = true)
{
if (voxels == null || voxels.Length == 0 || size.x <= 0 || size.y <= 0 || size.z <= 0)
{
return false;
}
float num = radius / CurrentVoxelSize;
float radiusSquared = num * num;
Vector3 center = base.transform.InverseTransformPoint(worldCenter) / CurrentVoxelSize;
float num2 = num + 0.5f;
int num3 = Mathf.Clamp(Mathf.FloorToInt(center.x - num2), 0, size.x - 1);
int num4 = Mathf.Clamp(Mathf.FloorToInt(center.y - num2), 0, size.y - 1);
int num5 = Mathf.Clamp(Mathf.FloorToInt(center.z - num2), 0, size.z - 1);
int num6 = Mathf.Clamp(Mathf.FloorToInt(center.x + num2), 0, size.x - 1);
int num7 = Mathf.Clamp(Mathf.FloorToInt(center.y + num2), 0, size.y - 1);
int num8 = Mathf.Clamp(Mathf.FloorToInt(center.z + num2), 0, size.z - 1);
bool flag = false;
for (int i = num5; i <= num8; i++)
{
for (int j = num4; j <= num7; j++)
{
for (int k = num3; k <= num6; k++)
{
if (!PackedVoxel.IsAir(GetVoxel(k, j, i)) && SphereIntersectsCell(center, radiusSquared, k, j, i))
{
voxels[GetFlatIndex(k, j, i)] = 0;
flag = true;
}
}
}
}
if (flag && (markMeshDirty || markColliderDirty))
{
MarkDirty(markMeshDirty, markColliderDirty);
}
return flag;
}
private static bool SphereIntersectsCell(Vector3 center, float radiusSquared, int x, int y, int z)
{
float num = 0f;
if (center.x < (float)x)
{
num = (float)x - center.x;
}
else if (center.x > (float)x + 1f)
{
num = center.x - ((float)x + 1f);
}
float num2 = 0f;
if (center.y < (float)y)
{
num2 = (float)y - center.y;
}
else if (center.y > (float)y + 1f)
{
num2 = center.y - ((float)y + 1f);
}
float num3 = 0f;
if (center.z < (float)z)
{
num3 = (float)z - center.z;
}
else if (center.z > (float)z + 1f)
{
num3 = center.z - ((float)z + 1f);
}
return num * num + num2 * num2 + num3 * num3 <= radiusSquared;
}
public bool PaintSphere(Vector3 worldCenter, float radius, byte value, bool markMeshDirty = true, bool markColliderDirty = true)
{
if (PackedVoxel.IsAir(value) || voxels == null || voxels.Length == 0 || size.x <= 0 || size.y <= 0 || size.z <= 0)
{
return false;
}
float num = radius / CurrentVoxelSize;
float num2 = num * num;
Vector3 vector = base.transform.InverseTransformPoint(worldCenter) / CurrentVoxelSize;
int num3 = Mathf.Clamp(Mathf.FloorToInt(vector.x - num), 0, size.x - 1);
int num4 = Mathf.Clamp(Mathf.FloorToInt(vector.y - num), 0, size.y - 1);
int num5 = Mathf.Clamp(Mathf.FloorToInt(vector.z - num), 0, size.z - 1);
int num6 = Mathf.Clamp(Mathf.FloorToInt(vector.x + num), 0, size.x - 1);
int num7 = Mathf.Clamp(Mathf.FloorToInt(vector.y + num), 0, size.y - 1);
int num8 = Mathf.Clamp(Mathf.FloorToInt(vector.z + num), 0, size.z - 1);
bool flag = false;
for (int i = num5; i <= num8; i++)
{
for (int j = num4; j <= num7; j++)
{
for (int k = num3; k <= num6; k++)
{
int flatIndex = GetFlatIndex(k, j, i);
byte b = voxels[flatIndex];
if (!PackedVoxel.IsAir(b) && b != value && !((new Vector3((float)k + 0.5f, (float)j + 0.5f, (float)i + 0.5f) - vector).sqrMagnitude > num2))
{
voxels[flatIndex] = value;
flag = true;
}
}
}
}
if (flag && (markMeshDirty || markColliderDirty))
{
MarkDirty(markMeshDirty, markColliderDirty);
}
return flag;
}
public bool RepaintAll(byte value, bool markMeshDirty = true, bool markColliderDirty = false)
{
if (PackedVoxel.IsAir(value) || voxels == null || voxels.Length == 0)
{
return false;
}
bool flag = false;
for (int i = 0; i < voxels.Length; i++)
{
byte b = voxels[i];
if (!PackedVoxel.IsAir(b) && b != value)
{
voxels[i] = value;
flag = true;
}
}
if (flag && (markMeshDirty || markColliderDirty))
{
MarkDirty(markMeshDirty, markColliderDirty);
}
return flag;
}
public bool IntersectsSphere(Vector3 worldCenter, float radius)
{
if (size.x <= 0 || size.y <= 0 || size.z <= 0)
{
return false;
}
Vector3 vector = base.transform.InverseTransformPoint(worldCenter) / CurrentVoxelSize;
Vector3 zero = Vector3.zero;
Vector3 vector2 = size;
float num = 0f;
for (int i = 0; i < 3; i++)
{
float num2 = vector[i];
if (num2 < zero[i])
{
float num3 = zero[i] - num2;
num += num3 * num3;
}
else if (num2 > vector2[i])
{
float num4 = num2 - vector2[i];
num += num4 * num4;
}
}
float num5 = radius / CurrentVoxelSize;
return num <= num5 * num5;
}
public bool TrimToContents()
{
if (voxels == null || voxels.Length == 0)
{
size = Vector3Int.zero;
return false;
}
int num = size.x;
int num2 = size.y;
int num3 = size.z;
int num4 = -1;
int num5 = -1;
int num6 = -1;
for (int i = 0; i < size.z; i++)
{
for (int j = 0; j < size.y; j++)
{
for (int k = 0; k < size.x; k++)
{
if (!PackedVoxel.IsAir(voxels[GetFlatIndex(k, j, i)]))
{
if (k < num)
{
num = k;
}
if (j < num2)
{
num2 = j;
}
if (i < num3)
{
num3 = i;
}
if (k > num4)
{
num4 = k;
}
if (j > num5)
{
num5 = j;
}
if (i > num6)
{
num6 = i;
}
}
}
}
}
if (num4 < 0 || num5 < 0 || num6 < 0)
{
size = Vector3Int.zero;
return false;
}
if (num == 0 && num2 == 0 && num3 == 0 && num4 == size.x - 1 && num5 == size.y - 1 && num6 == size.z - 1)
{
return true;
}
Vector3Int localOffset = new Vector3Int(num, num2, num3);
Vector3Int vector3Int = new Vector3Int(num4 - num + 1, num5 - num2 + 1, num6 - num3 + 1);
byte[] array = new byte[vector3Int.x * vector3Int.y * vector3Int.z];
for (int l = num3; l <= num6; l++)
{
for (int m = num2; m <= num5; m++)
{
for (int n = num; n <= num4; n++)
{
byte b = voxels[GetFlatIndex(n, m, l)];
if (!PackedVoxel.IsAir(b))
{
int num7 = n - num;
int num8 = m - num2;
int num9 = l - num3;
int num10 = num7 + num8 * vector3Int.x + num9 * vector3Int.x * vector3Int.y;
array[num10] = b;
}
}
}
}
voxels = array;
size = vector3Int;
position += GridRotationUtility.Rotate(localOffset, packedRotation);
ApplyGridTransform();
return true;
}
internal void SetOwner(VoxelGroupManager manager)
{
owner = manager;
creatorMode = owner != null && owner.CreatorMode;
ApplyGridTransform();
BindMaterials((owner != null) ? owner.SharedMaterials : null);
}
internal void SetUseLocalGridTransform(bool useLocalGrid)
{
if (useLocalGridTransform != useLocalGrid)
{
useLocalGridTransform = useLocalGrid;
ApplyGridTransform();
}
}
internal void OverwriteData(Vector3Int gridPosition, byte rotation, Vector3Int groupSize, byte[] voxelData, bool queueRebuild = true)
{
position = gridPosition;
packedRotation = rotation;
size = groupSize;
voxels = voxelData ?? new byte[0];
creatorMode = owner != null && owner.CreatorMode;
EnsureComponents();
ApplyGridTransform();
BindMaterials((owner != null) ? owner.SharedMaterials : null);
SetSelected(selected: false);
if (queueRebuild)
{
MarkDirty(mesh: true, collider: true);
return;
}
dirtyMesh = false;
dirtyCollider = false;
}
internal void SetGridPose(Vector3Int gridPosition, byte rotation)
{
if (!(position == gridPosition) || packedRotation != rotation)
{
position = gridPosition;
packedRotation = rotation;
ApplyGridTransform();
}
}
internal bool SetWorldVoxel(Vector3Int worldCell, byte value, bool markMeshDirty, bool markColliderDirty)
{
EnsureStorageForStoredCell(WorldGridCellToStoredCell(worldCell));
if (size.x <= 0 || size.y <= 0 || size.z <= 0 || voxels == null || voxels.Length == 0)
{
return false;
}
Vector3Int vector3Int = StoredCellToLocalCell(WorldGridCellToStoredCell(worldCell));
if (!IsInBounds(vector3Int.x, vector3Int.y, vector3Int.z))
{
return false;
}
int flatIndex = GetFlatIndex(vector3Int.x, vector3Int.y, vector3Int.z);
if (voxels[flatIndex] == value)
{
return false;
}
voxels[flatIndex] = value;
if (markMeshDirty || markColliderDirty)
{
MarkDirty(markMeshDirty, markColliderDirty);
}
return true;
}
internal bool SetStoredVoxel(Vector3Int storedCell, byte value, bool markMeshDirty, bool markColliderDirty)
{
EnsureStorageForStoredCell(storedCell);
if (size.x <= 0 || size.y <= 0 || size.z <= 0 || voxels == null || voxels.Length == 0)
{
return false;
}
Vector3Int vector3Int = StoredCellToLocalCell(storedCell);
if (!IsInBounds(vector3Int.x, vector3Int.y, vector3Int.z))
{
return false;
}
int flatIndex = GetFlatIndex(vector3Int.x, vector3Int.y, vector3Int.z);
if (voxels[flatIndex] == value)
{
return false;
}
voxels[flatIndex] = value;
if (markMeshDirty || markColliderDirty)
{
MarkDirty(markMeshDirty, markColliderDirty);
}
return true;
}
internal Vector3Int WorldPointToStoredGridCell(Vector3 worldPoint)
{
if (useLocalGridTransform && base.transform.parent != null)
{
Vector3 vector = base.transform.parent.InverseTransformPoint(worldPoint) / CurrentVoxelSize;
return new Vector3Int(Mathf.RoundToInt(vector.x), Mathf.RoundToInt(vector.y), Mathf.RoundToInt(vector.z));
}
Vector3 vector2 = worldPoint / CurrentVoxelSize;
return new Vector3Int(Mathf.RoundToInt(vector2.x), Mathf.RoundToInt(vector2.y), Mathf.RoundToInt(vector2.z));
}
internal void SetCreatorMode(bool enabled)
{
if (creatorMode != enabled)
{
creatorMode = enabled;
MarkDirty(mesh: true, collider: false);
}
}
internal bool TryPickNearestVoxelValue(Vector3 worldPoint, float maxRadius, out byte voxelValue, out Vector3 pickedWorldCenter, out float pickedDistanceSquared)
{
voxelValue = 0;
pickedWorldCenter = Vector3.zero;
pickedDistanceSquared = 0f;
if (voxels == null || voxels.Length == 0 || size.x <= 0 || size.y <= 0 || size.z <= 0)
{
return false;
}
float currentVoxelSize = CurrentVoxelSize;
if (currentVoxelSize <= 0f)
{
return false;
}
float num = maxRadius * maxRadius;
Vector3 vector = base.transform.InverseTransformPoint(worldPoint) / currentVoxelSize;
float num2 = maxRadius / currentVoxelSize;
int num3 = Mathf.Max(0, Mathf.FloorToInt(vector.x - num2));
int num4 = Mathf.Max(0, Mathf.FloorToInt(vector.y - num2));
int num5 = Mathf.Max(0, Mathf.FloorToInt(vector.z - num2));
int num6 = Mathf.Min(size.x - 1, Mathf.CeilToInt(vector.x + num2));
int num7 = Mathf.Min(size.y - 1, Mathf.CeilToInt(vector.y + num2));
int num8 = Mathf.Min(size.z - 1, Mathf.CeilToInt(vector.z + num2));
float num9 = num;
bool result = false;
for (int i = num5; i <= num8; i++)
{
for (int j = num4; j <= num7; j++)
{
for (int k = num3; k <= num6; k++)
{
byte voxel = GetVoxel(k, j, i);
if (!PackedVoxel.IsAir(voxel))
{
Vector3 vector2 = new Vector3(((float)k + 0.5f) * currentVoxelSize, ((float)j + 0.5f) * currentVoxelSize, ((float)i + 0.5f) * currentVoxelSize);
Vector3 vector3 = base.transform.TransformPoint(vector2);
float sqrMagnitude = (vector3 - worldPoint).sqrMagnitude;
if (!(sqrMagnitude > num9))
{
result = true;
num9 = sqrMagnitude;
voxelValue = voxel;
pickedWorldCenter = vector3;
}
}
}
}
}
pickedDistanceSquared = num9;
return result;
}
public void SetVoxelSizeScale(float scale, bool rebuild = true)
{
scale = Mathf.Max(0.001f, scale);
if (!Mathf.Approximately(voxelSizeScale, scale))
{
voxelSizeScale = scale;
ApplyGridTransform();
if (rebuild)
{
RebuildMesh();
RebuildCollider();
}
else
{
dirtyMesh = true;
dirtyCollider = true;
}
}
}
internal void SetSelected(bool selected)
{
if (IsSelected != selected)
{
IsSelected = selected;
ApplySelectionVisual();
}
}
internal void SetGreedyRenderMeshing(bool enabled)
{
useGreedyRenderMeshing = enabled;
if (!enabled)
{
EnsureComponents();
meshCollider.sharedMesh = null;
meshCollider.enabled = false;
dirtyCollider = false;
}
}
internal void SetColliderGeneration(bool enabled)
{
allowColliderGeneration = enabled;
if (!enabled)
{
EnsureComponents();
meshCollider.sharedMesh = null;
meshCollider.enabled = false;
dirtyCollider = false;
}
}
internal void BindMaterials(Material[] materials)
{
EnsureComponents();
if (materials != null && materials.Length != 0)
{
meshRenderer.sharedMaterial = ((materials.Length != 0) ? materials[0] : null);
unlitMeshRenderer.sharedMaterial = ((materials.Length > 1) ? materials[1] : meshRenderer.sharedMaterial);
transparentMeshRenderer.sharedMaterial = ((materials.Length > 2) ? materials[2] : meshRenderer.sharedMaterial);
invisibleMeshRenderer.sharedMaterial = ((materials.Length > 3) ? materials[3] : transparentMeshRenderer.sharedMaterial);
ApplySelectionVisual();
}
}
internal void MarkDirty(bool mesh, bool collider)
{
if (mesh)
{
dirtyMesh = true;
}
if (collider)
{
dirtyCollider = true;
}
owner?.QueueRebuild(this);
}
internal int GetFlatIndex(int x, int y, int z)
{
return x + y * size.x + z * size.x * size.y;
}
private void Awake()
{
EnsureComponents();
}
private void OnDestroy()
{
if (renderMesh != null)
{
Object.Destroy(renderMesh);
}
if (renderMeshUnlit != null)
{
Object.Destroy(renderMeshUnlit);
}
if (renderMeshTransparent != null)
{
Object.Destroy(renderMeshTransparent);
}
if (renderMeshInvisible != null)
{
Object.Destroy(renderMeshInvisible);
}
if (collisionMesh != null)
{
Object.Destroy(collisionMesh);
}
}
private void EnsureComponents()
{
if (meshFilter == null && !TryGetComponent<MeshFilter>(out meshFilter))
{
meshFilter = base.gameObject.AddComponent<MeshFilter>();
}
if (meshRenderer == null && !TryGetComponent<MeshRenderer>(out meshRenderer))
{
meshRenderer = base.gameObject.AddComponent<MeshRenderer>();
}
EnsureChildRenderer("Render_Unlit", ref unlitMeshFilter, ref unlitMeshRenderer);
EnsureChildRenderer("Render_Transparent", ref transparentMeshFilter, ref transparentMeshRenderer);
EnsureChildRenderer("Render_Invisible", ref invisibleMeshFilter, ref invisibleMeshRenderer);
if (meshCollider == null && !TryGetComponent<MeshCollider>(out meshCollider))
{
meshCollider = base.gameObject.AddComponent<MeshCollider>();
}
meshRenderer.shadowCastingMode = ShadowCastingMode.On;
meshRenderer.receiveShadows = true;
unlitMeshRenderer.shadowCastingMode = ShadowCastingMode.On;
unlitMeshRenderer.receiveShadows = true;
transparentMeshRenderer.shadowCastingMode = ShadowCastingMode.Off;
transparentMeshRenderer.receiveShadows = false;
invisibleMeshRenderer.shadowCastingMode = ShadowCastingMode.Off;
invisibleMeshRenderer.receiveShadows = false;
ApplySelectionVisual();
}
private void EnsureChildRenderer(string name, ref MeshFilter filter, ref MeshRenderer renderer)
{
if (!(filter != null) || !(renderer != null))
{
Transform transform = base.transform.Find(name);
if (transform == null)
{
GameObject obj = new GameObject(name);
obj.transform.SetParent(base.transform, worldPositionStays: false);
transform = obj.transform;
}
if (!transform.TryGetComponent<MeshFilter>(out filter))
{
filter = transform.gameObject.AddComponent<MeshFilter>();
}
if (!transform.TryGetComponent<MeshRenderer>(out renderer))
{
renderer = transform.gameObject.AddComponent<MeshRenderer>();
}
}
}
private void ApplyGridTransform()
{
Vector3 localPosition = (Vector3)position * CurrentVoxelSize;
Quaternion quaternion = GridRotationUtility.ToQuaternion(packedRotation);
if (useLocalGridTransform)
{
base.transform.localPosition = localPosition;
base.transform.localRotation = quaternion;
}
else
{
base.transform.SetPositionAndRotation(localPosition, quaternion);
}
}
private void ApplyMeshSubmesh(Mesh mesh, GreedyMesher.MeshData meshData, int submeshIndex, bool applyColors)
{
mesh.Clear();
mesh.indexFormat = IndexFormat.UInt32;
mesh.subMeshCount = 1;
mesh.SetVertices(meshData.Vertices);
mesh.SetNormals(meshData.Normals);
if (applyColors)
{
mesh.SetColors(meshData.Colors);
mesh.SetUVs(0, meshData.Uvs);
}
if (submeshIndex >= 0 && submeshIndex < meshData.SubmeshTriangles.Length)
{
mesh.SetTriangles(meshData.SubmeshTriangles[submeshIndex], 0, calculateBounds: false);
}
mesh.RecalculateBounds();
}
private void ApplySelectionVisual()
{
if (!(meshRenderer == null))
{
if (propertyBlock == null)
{
propertyBlock = new MaterialPropertyBlock();
}
propertyBlock.Clear();
Color color = (IsSelected ? SelectedTintColor : Color.white);
propertyBlock.SetColor(BaseColorId, color);
propertyBlock.SetColor(ColorId, color);
propertyBlock.SetColor(TintColorId, color);
propertyBlock.SetColor(EmissionColorId, IsSelected ? (color * 0.06f) : Color.black);
propertyBlock.SetColor(EmissiveColorId, IsSelected ? (color * 0.06f) : Color.black);
meshRenderer.SetPropertyBlock(propertyBlock);
unlitMeshRenderer?.SetPropertyBlock(propertyBlock);
transparentMeshRenderer?.SetPropertyBlock(propertyBlock);
invisibleMeshRenderer?.SetPropertyBlock(propertyBlock);
}
}
private bool IsInBounds(int x, int y, int z)
{
if (x >= 0 && y >= 0 && z >= 0 && x < size.x && y < size.y)
{
return z < size.z;
}
return false;
}
private void EnsureStorageForStoredCell(Vector3Int storedCell)
{
if (voxels == null || voxels.Length == 0 || size.x <= 0 || size.y <= 0 || size.z <= 0)
{
position = storedCell;
size = Vector3Int.one;
voxels = new byte[1];
ApplyGridTransform();
return;
}
Vector3Int vector3Int = StoredCellToLocalCell(storedCell);
Vector3Int vector3Int2 = new Vector3Int(Mathf.Min(0, vector3Int.x), Mathf.Min(0, vector3Int.y), Mathf.Min(0, vector3Int.z));
Vector3Int vector3Int3 = new Vector3Int(Mathf.Max(size.x - 1, vector3Int.x), Mathf.Max(size.y - 1, vector3Int.y), Mathf.Max(size.z - 1, vector3Int.z));
if (vector3Int2 == Vector3Int.zero && vector3Int3.x == size.x - 1 && vector3Int3.y == size.y - 1 && vector3Int3.z == size.z - 1)
{
return;
}
Vector3Int vector3Int4 = new Vector3Int(vector3Int3.x - vector3Int2.x + 1, vector3Int3.y - vector3Int2.y + 1, vector3Int3.z - vector3Int2.z + 1);
byte[] array = new byte[vector3Int4.x * vector3Int4.y * vector3Int4.z];
for (int i = 0; i < size.z; i++)
{
for (int j = 0; j < size.y; j++)
{
for (int k = 0; k < size.x; k++)
{
byte b = voxels[GetFlatIndex(k, j, i)];
if (!PackedVoxel.IsAir(b))
{
int num = k - vector3Int2.x;
int num2 = j - vector3Int2.y;
int num3 = i - vector3Int2.z;
int num4 = num + num2 * vector3Int4.x + num3 * vector3Int4.x * vector3Int4.y;
array[num4] = b;
}
}
}
}
voxels = array;
size = vector3Int4;
position += GridRotationUtility.Rotate(vector3Int2, packedRotation);
ApplyGridTransform();
}
private Vector3Int StoredCellToLocalCell(Vector3Int storedCell)
{
return GridRotationUtility.InverseRotate(storedCell - position, packedRotation);
}
private Vector3Int WorldGridCellToStoredCell(Vector3Int worldCell)
{
if (!useLocalGridTransform || base.transform.parent == null)
{
return worldCell;
}
Vector3 vector = base.transform.parent.InverseTransformPoint((Vector3)worldCell * CurrentVoxelSize) / CurrentVoxelSize;
return new Vector3Int(Mathf.RoundToInt(vector.x), Mathf.RoundToInt(vector.y), Mathf.RoundToInt(vector.z));
}
}
}