257 lines
6.6 KiB
C#
257 lines
6.6 KiB
C#
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using HG;
|
||
|
using RoR2.Navigation;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.Serialization;
|
||
|
|
||
|
namespace RoR2;
|
||
|
|
||
|
public class SceneInfo : MonoBehaviour
|
||
|
{
|
||
|
private static class NodeGraphOverlay
|
||
|
{
|
||
|
private static Dictionary<(MapNodeGroup.GraphType graphType, HullMask hullMask), (DebugOverlay.MeshDrawer drawer, Action updater)> drawers;
|
||
|
|
||
|
private static void StaticUpdate()
|
||
|
{
|
||
|
foreach (KeyValuePair<(MapNodeGroup.GraphType, HullMask), (DebugOverlay.MeshDrawer, Action)> drawer in drawers)
|
||
|
{
|
||
|
drawer.Value.Item2();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void SetGraphDrawEnabled(bool shouldDraw, MapNodeGroup.GraphType graphType, HullMask hullMask)
|
||
|
{
|
||
|
(MapNodeGroup.GraphType, HullMask) key = (graphType, hullMask);
|
||
|
DebugOverlay.MeshDrawer drawer;
|
||
|
GenericMemoizer<(DebugOverlay.MeshDrawer, SceneInfo, MapNodeGroup.GraphType, HullMask), Mesh> getNodeGraphMeshMemoizer;
|
||
|
if (shouldDraw)
|
||
|
{
|
||
|
if (drawers == null)
|
||
|
{
|
||
|
drawers = new Dictionary<(MapNodeGroup.GraphType, HullMask), (DebugOverlay.MeshDrawer, Action)>();
|
||
|
RoR2Application.onUpdate += StaticUpdate;
|
||
|
}
|
||
|
if (!drawers.ContainsKey(key))
|
||
|
{
|
||
|
drawer = DebugOverlay.GetMeshDrawer();
|
||
|
drawer.hasMeshOwnership = true;
|
||
|
drawer.material = DebugOverlay.defaultWireMaterial;
|
||
|
getNodeGraphMeshMemoizer = new GenericMemoizer<(DebugOverlay.MeshDrawer, SceneInfo, MapNodeGroup.GraphType, HullMask), Mesh>(GetNodeGraphMesh);
|
||
|
drawers.Add(key, (drawer, Updater));
|
||
|
}
|
||
|
}
|
||
|
else if (drawers != null)
|
||
|
{
|
||
|
if (drawers.TryGetValue(key, out (DebugOverlay.MeshDrawer, Action) value))
|
||
|
{
|
||
|
value.Item1.Dispose();
|
||
|
drawers.Remove(key);
|
||
|
}
|
||
|
if (drawers.Count == 0)
|
||
|
{
|
||
|
drawers = null;
|
||
|
RoR2Application.onUpdate -= StaticUpdate;
|
||
|
}
|
||
|
}
|
||
|
static Mesh GetNodeGraphMesh(in (DebugOverlay.MeshDrawer, SceneInfo sceneInfo, MapNodeGroup.GraphType graphType, HullMask hullMask) input)
|
||
|
{
|
||
|
return input.sceneInfo?.GetNodeGraph(input.graphType).GenerateLinkDebugMesh(input.hullMask);
|
||
|
}
|
||
|
void Updater()
|
||
|
{
|
||
|
DebugOverlay.MeshDrawer meshDrawer = drawer;
|
||
|
ref GenericMemoizer<(DebugOverlay.MeshDrawer, SceneInfo, MapNodeGroup.GraphType, HullMask), Mesh> reference = ref getNodeGraphMeshMemoizer;
|
||
|
(DebugOverlay.MeshDrawer, SceneInfo, MapNodeGroup.GraphType, HullMask) input2 = (drawer, instance, graphType, hullMask);
|
||
|
meshDrawer.mesh = reference.Evaluate(in input2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[ConCommand(commandName = "debug_scene_draw_nodegraph", flags = ConVarFlags.Cheat, helpText = "Enables/disables overlay drawing of the specified nodegraph. Format: {shouldDraw} {graphType} {hullClassification, ...}")]
|
||
|
private static void CCDebugSceneDrawNodegraph(ConCommandArgs args)
|
||
|
{
|
||
|
bool argBool = args.GetArgBool(0);
|
||
|
MapNodeGroup.GraphType argEnum = args.GetArgEnum<MapNodeGroup.GraphType>(1);
|
||
|
HullMask hullMask = (HullMask)(1 << (int)args.GetArgEnum<HullClassification>(2));
|
||
|
if (hullMask == HullMask.None)
|
||
|
{
|
||
|
throw new ConCommandException("Cannot use HullMask.None.");
|
||
|
}
|
||
|
for (int i = 3; i < args.Count; i++)
|
||
|
{
|
||
|
HullClassification? hullClassification = args.TryGetArgEnum<HullClassification>(i);
|
||
|
if (hullClassification.HasValue)
|
||
|
{
|
||
|
hullMask = (HullMask)((int)hullMask | (1 << (int)hullClassification.Value));
|
||
|
}
|
||
|
}
|
||
|
SetGraphDrawEnabled(argBool, argEnum, hullMask);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static SceneInfo _instance;
|
||
|
|
||
|
[FormerlySerializedAs("groundNodes")]
|
||
|
public MapNodeGroup groundNodeGroup;
|
||
|
|
||
|
[FormerlySerializedAs("airNodes")]
|
||
|
public MapNodeGroup airNodeGroup;
|
||
|
|
||
|
[FormerlySerializedAs("railNodes")]
|
||
|
public MapNodeGroup railNodeGroup;
|
||
|
|
||
|
public MeshRenderer approximateMapBoundMesh;
|
||
|
|
||
|
[SerializeField]
|
||
|
private NodeGraph groundNodesAsset;
|
||
|
|
||
|
[SerializeField]
|
||
|
private NodeGraph airNodesAsset;
|
||
|
|
||
|
public static SceneInfo instance => _instance;
|
||
|
|
||
|
public NodeGraph groundNodes { get; private set; }
|
||
|
|
||
|
public NodeGraph airNodes { get; private set; }
|
||
|
|
||
|
public NodeGraph railNodes { get; private set; }
|
||
|
|
||
|
public SceneDef sceneDef { get; private set; }
|
||
|
|
||
|
public bool countsAsStage
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (!sceneDef)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
if (sceneDef.sceneType != SceneType.Stage)
|
||
|
{
|
||
|
return sceneDef.sceneType == SceneType.UntimedStage;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void Awake()
|
||
|
{
|
||
|
if ((bool)groundNodesAsset)
|
||
|
{
|
||
|
groundNodes = UnityEngine.Object.Instantiate(groundNodesAsset);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Debug.LogWarning(base.gameObject.scene.name + " has no groundNodesAsset");
|
||
|
}
|
||
|
if ((bool)airNodesAsset)
|
||
|
{
|
||
|
airNodes = UnityEngine.Object.Instantiate(airNodesAsset);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Debug.LogWarning(base.gameObject.scene.name + " has no airNodesAsset");
|
||
|
}
|
||
|
sceneDef = SceneCatalog.GetSceneDefFromSceneName(base.gameObject.scene.name);
|
||
|
}
|
||
|
|
||
|
private void Start()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
private void RemoveCollisionFromParticleSystems()
|
||
|
{
|
||
|
ParticleSystem[] array = UnityEngine.Object.FindObjectsOfType<ParticleSystem>();
|
||
|
int num = 0;
|
||
|
ParticleSystem[] array2 = array;
|
||
|
for (int i = 0; i < array2.Length; i++)
|
||
|
{
|
||
|
ParticleSystem.CollisionModule collision = array2[i].collision;
|
||
|
if (collision.enabled)
|
||
|
{
|
||
|
num++;
|
||
|
}
|
||
|
collision.enabled = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void OnDestroy()
|
||
|
{
|
||
|
UnityEngine.Object.Destroy(groundNodes);
|
||
|
UnityEngine.Object.Destroy(airNodes);
|
||
|
UnityEngine.Object.Destroy(railNodes);
|
||
|
}
|
||
|
|
||
|
public MapNodeGroup GetNodeGroup(MapNodeGroup.GraphType nodeGraphType)
|
||
|
{
|
||
|
return nodeGraphType switch
|
||
|
{
|
||
|
MapNodeGroup.GraphType.Ground => groundNodeGroup,
|
||
|
MapNodeGroup.GraphType.Air => airNodeGroup,
|
||
|
MapNodeGroup.GraphType.Rail => railNodeGroup,
|
||
|
_ => null,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
public NodeGraph GetNodeGraph(MapNodeGroup.GraphType nodeGraphType)
|
||
|
{
|
||
|
return nodeGraphType switch
|
||
|
{
|
||
|
MapNodeGroup.GraphType.Ground => groundNodes,
|
||
|
MapNodeGroup.GraphType.Air => airNodes,
|
||
|
MapNodeGroup.GraphType.Rail => railNodes,
|
||
|
_ => null,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
public void SetGateState(string gateName, bool gateEnabled)
|
||
|
{
|
||
|
bool flag = false;
|
||
|
if ((bool)groundNodes)
|
||
|
{
|
||
|
flag = groundNodes.TrySetGateState(gateName, gateEnabled) || flag;
|
||
|
}
|
||
|
if ((bool)airNodes)
|
||
|
{
|
||
|
flag = airNodes.TrySetGateState(gateName, gateEnabled) || flag;
|
||
|
}
|
||
|
if ((bool)railNodes)
|
||
|
{
|
||
|
flag = railNodes.TrySetGateState(gateName, gateEnabled) || flag;
|
||
|
}
|
||
|
if (!flag)
|
||
|
{
|
||
|
Debug.LogError($"Unable to set gate state for {base.gameObject.scene.name}: {gateName}={gateEnabled}");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void OnEnable()
|
||
|
{
|
||
|
if (!_instance)
|
||
|
{
|
||
|
_instance = this;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void OnDisable()
|
||
|
{
|
||
|
if (_instance == this)
|
||
|
{
|
||
|
_instance = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void OnValidate()
|
||
|
{
|
||
|
if ((bool)groundNodeGroup)
|
||
|
{
|
||
|
groundNodesAsset = groundNodeGroup.nodeGraph;
|
||
|
}
|
||
|
if ((bool)airNodeGroup)
|
||
|
{
|
||
|
airNodesAsset = airNodeGroup.nodeGraph;
|
||
|
}
|
||
|
}
|
||
|
}
|