LethalCompany/Lethal Company/ExportedProject/Assets/Scripts/Assembly-CSharp/DunGen/BasicRoomCullingCamera.cs
2023-12-22 18:30:10 -05:00

389 lines
9.4 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
namespace DunGen
{
[AddComponentMenu("DunGen/Culling/Adjacent Room Culling (Multi-Camera)")]
public class BasicRoomCullingCamera : MonoBehaviour
{
protected struct RendererData
{
public Renderer Renderer;
public bool Enabled;
public RendererData(Renderer renderer, bool enabled)
{
Renderer = renderer;
Enabled = enabled;
}
}
protected struct LightData
{
public Light Light;
public bool Enabled;
public LightData(Light light, bool enabled)
{
Light = light;
Enabled = enabled;
}
}
protected struct ReflectionProbeData
{
public ReflectionProbe Probe;
public bool Enabled;
public ReflectionProbeData(ReflectionProbe probe, bool enabled)
{
Probe = probe;
Enabled = enabled;
}
}
public int AdjacentTileDepth = 1;
public bool CullBehindClosedDoors = true;
public Transform TargetOverride;
public bool CullInEditor;
public bool CullLights = true;
protected bool isCulling;
protected bool isDirty;
protected DungeonGenerator generator;
protected Tile currentTile;
protected List<Tile> allTiles;
protected List<Door> allDoors;
protected List<Tile> visibleTiles;
protected Dictionary<Tile, List<RendererData>> rendererVisibilities = new Dictionary<Tile, List<RendererData>>();
protected Dictionary<Tile, List<LightData>> lightVisibilities = new Dictionary<Tile, List<LightData>>();
protected Dictionary<Tile, List<ReflectionProbeData>> reflectionProbeVisibilities = new Dictionary<Tile, List<ReflectionProbeData>>();
protected Dictionary<Door, List<RendererData>> doorRendererVisibilities = new Dictionary<Door, List<RendererData>>();
public bool IsReady { get; protected set; }
protected virtual void Awake()
{
RuntimeDungeon runtimeDungeon = UnityEngine.Object.FindObjectOfType<RuntimeDungeon>();
if (runtimeDungeon != null)
{
generator = runtimeDungeon.Generator;
generator.OnGenerationStatusChanged += OnDungeonGenerationStatusChanged;
if (generator.Status == GenerationStatus.Complete)
{
SetDungeon(generator.CurrentDungeon);
}
}
}
protected virtual void OnDestroy()
{
if (generator != null)
{
generator.OnGenerationStatusChanged -= OnDungeonGenerationStatusChanged;
}
}
protected virtual void OnEnable()
{
if (RenderPipelineManager.currentPipeline != null)
{
RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering;
RenderPipelineManager.endCameraRendering += OnEndCameraRendering;
}
else
{
Camera.onPreCull = (Camera.CameraCallback)Delegate.Combine(Camera.onPreCull, new Camera.CameraCallback(EnableCulling));
Camera.onPostRender = (Camera.CameraCallback)Delegate.Combine(Camera.onPostRender, new Camera.CameraCallback(DisableCulling));
}
}
protected virtual void OnDisable()
{
RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
RenderPipelineManager.endCameraRendering -= OnEndCameraRendering;
Camera.onPreCull = (Camera.CameraCallback)Delegate.Remove(Camera.onPreCull, new Camera.CameraCallback(EnableCulling));
Camera.onPostRender = (Camera.CameraCallback)Delegate.Remove(Camera.onPostRender, new Camera.CameraCallback(DisableCulling));
}
private void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
{
EnableCulling(camera);
}
private void OnEndCameraRendering(ScriptableRenderContext context, Camera camera)
{
DisableCulling(camera);
}
protected virtual void OnDungeonGenerationStatusChanged(DungeonGenerator generator, GenerationStatus status)
{
switch (status)
{
case GenerationStatus.Complete:
SetDungeon(generator.CurrentDungeon);
break;
case GenerationStatus.Failed:
ClearDungeon();
break;
}
}
protected virtual void EnableCulling(Camera camera)
{
SetCullingEnabled(camera, enabled: true);
}
protected virtual void DisableCulling(Camera camera)
{
SetCullingEnabled(camera, enabled: false);
}
protected void SetCullingEnabled(Camera camera, bool enabled)
{
if (IsReady && camera.gameObject == base.gameObject)
{
SetIsCulling(enabled);
}
}
protected virtual void LateUpdate()
{
if (!IsReady)
{
return;
}
Transform transform = ((TargetOverride != null) ? TargetOverride : base.transform);
if (currentTile == null || !currentTile.Bounds.Contains(transform.position))
{
foreach (Tile allTile in allTiles)
{
if (!(allTile == null) && allTile.Bounds.Contains(transform.position))
{
currentTile = allTile;
break;
}
}
isDirty = true;
}
if (!isDirty)
{
return;
}
UpdateCulling();
foreach (Tile allTile2 in allTiles)
{
if (!visibleTiles.Contains(allTile2))
{
UpdateRendererList(allTile2);
}
}
}
protected void UpdateRendererList(Tile tile)
{
if (!rendererVisibilities.TryGetValue(tile, out var value))
{
value = (rendererVisibilities[tile] = new List<RendererData>());
}
else
{
value.Clear();
}
Renderer[] componentsInChildren = tile.GetComponentsInChildren<Renderer>();
foreach (Renderer renderer in componentsInChildren)
{
value.Add(new RendererData(renderer, renderer.enabled));
}
if (CullLights)
{
if (!lightVisibilities.TryGetValue(tile, out var value2))
{
value2 = (lightVisibilities[tile] = new List<LightData>());
}
else
{
value2.Clear();
}
Light[] componentsInChildren2 = tile.GetComponentsInChildren<Light>();
foreach (Light light in componentsInChildren2)
{
value2.Add(new LightData(light, light.enabled));
}
}
if (!reflectionProbeVisibilities.TryGetValue(tile, out var value3))
{
value3 = (reflectionProbeVisibilities[tile] = new List<ReflectionProbeData>());
}
else
{
value3.Clear();
}
ReflectionProbe[] componentsInChildren3 = tile.GetComponentsInChildren<ReflectionProbe>();
foreach (ReflectionProbe reflectionProbe in componentsInChildren3)
{
value3.Add(new ReflectionProbeData(reflectionProbe, reflectionProbe.enabled));
}
}
protected void SetIsCulling(bool isCulling)
{
this.isCulling = isCulling;
for (int i = 0; i < allTiles.Count; i++)
{
Tile tile = allTiles[i];
if (visibleTiles.Contains(tile))
{
continue;
}
if (rendererVisibilities.TryGetValue(tile, out var value))
{
foreach (RendererData item in value)
{
item.Renderer.enabled = !isCulling && item.Enabled;
}
}
if (CullLights && lightVisibilities.TryGetValue(tile, out var value2))
{
foreach (LightData item2 in value2)
{
item2.Light.enabled = !isCulling && item2.Enabled;
}
}
if (!reflectionProbeVisibilities.TryGetValue(tile, out var value3))
{
continue;
}
foreach (ReflectionProbeData item3 in value3)
{
item3.Probe.enabled = !isCulling && item3.Enabled;
}
}
foreach (Door allDoor in allDoors)
{
bool flag = visibleTiles.Contains(allDoor.DoorwayA.Tile) || visibleTiles.Contains(allDoor.DoorwayB.Tile);
if (!doorRendererVisibilities.TryGetValue(allDoor, out var value4))
{
continue;
}
foreach (RendererData item4 in value4)
{
item4.Renderer.enabled = (isCulling ? flag : item4.Enabled);
}
}
}
protected void UpdateCulling()
{
isDirty = false;
visibleTiles.Clear();
if (currentTile != null)
{
visibleTiles.Add(currentTile);
}
int num = 0;
for (int i = 0; i < AdjacentTileDepth; i++)
{
int count = visibleTiles.Count;
for (int j = num; j < count; j++)
{
foreach (Doorway usedDoorway in visibleTiles[j].UsedDoorways)
{
Tile tile = usedDoorway.ConnectedDoorway.Tile;
if (visibleTiles.Contains(tile))
{
continue;
}
if (CullBehindClosedDoors)
{
Door doorComponent = usedDoorway.DoorComponent;
if (doorComponent != null && doorComponent.ShouldCullBehind)
{
continue;
}
}
visibleTiles.Add(tile);
}
}
num = count;
}
}
public void SetDungeon(Dungeon dungeon)
{
if (IsReady)
{
ClearDungeon();
}
if (dungeon == null)
{
return;
}
allTiles = new List<Tile>(dungeon.AllTiles);
allDoors = new List<Door>(GetAllDoorsInDungeon(dungeon));
visibleTiles = new List<Tile>(allTiles.Count);
doorRendererVisibilities.Clear();
foreach (Door allDoor in allDoors)
{
List<RendererData> list = new List<RendererData>();
doorRendererVisibilities[allDoor] = list;
Renderer[] componentsInChildren = allDoor.GetComponentsInChildren<Renderer>(includeInactive: true);
foreach (Renderer renderer in componentsInChildren)
{
list.Add(new RendererData(renderer, renderer.enabled));
}
allDoor.OnDoorStateChanged += OnDoorStateChanged;
}
IsReady = true;
isDirty = true;
}
protected IEnumerable<Door> GetAllDoorsInDungeon(Dungeon dungeon)
{
foreach (GameObject door in dungeon.Doors)
{
if (!(door == null))
{
Door component = door.GetComponent<Door>();
if (component != null)
{
yield return component;
}
}
}
}
protected virtual void ClearDungeon()
{
foreach (Door allDoor in allDoors)
{
allDoor.OnDoorStateChanged -= OnDoorStateChanged;
}
IsReady = false;
}
protected virtual void OnDoorStateChanged(Door door, bool isOpen)
{
isDirty = true;
}
}
}