ZeroVR/ZeroPacientVR/Assets/CodeRespawn/DungeonArchitect/Scripts/Builders/GridFlow/GridFlowDungeonModel.cs

179 lines
5.6 KiB
C#

//$ Copyright 2015-22, Code Respawn Technologies Pvt Ltd - All Rights Reserved $//
using System.Collections.Generic;
using UnityEngine;
using DungeonArchitect.Flow.Domains.Layout;
using DungeonArchitect.Flow.Domains.Tilemap;
using DungeonArchitect.Flow.Impl.GridFlow;
using DungeonArchitect.Utils;
namespace DungeonArchitect.Builders.GridFlow
{
public class GridFlowDungeonModel : DungeonModel
{
/// <summary>
/// The high level node based layout graph
/// </summary>
[HideInInspector]
[SerializeField]
private FlowLayoutGraph layoutGraph;
public FlowLayoutGraph LayoutGraph => layoutGraph;
/// <summary>
/// Rasterized tilemap representation of the abstract graph
/// </summary>
[HideInInspector]
[SerializeField]
private FlowTilemap tilemap;
public FlowTilemap Tilemap => tilemap;
/// <summary>
/// The size of the grid this dungeon was built with
/// </summary>
[HideInInspector]
[SerializeField]
private Vector3 gridSize;
/// <summary>
/// Walls in the grid flow builder can either take up a full tile or are built as edges
/// This is controlled from the "Initial Tilemap" node's property in the grid flow execution graph
/// </summary>
[HideInInspector]
public bool wallsAsEdges = false;
[HideInInspector]
[SerializeField]
private GridFlowDungeonQuery query;
public GridFlowDungeonQuery Query { get => query; }
public void Initialize(FlowLayoutGraph inLayoutGraph, FlowTilemap inTilemap, Vector3 inGridSize)
{
layoutGraph = inLayoutGraph;
tilemap = inTilemap;
gridSize = inGridSize;
query = GetComponent<GridFlowDungeonQuery>();
lookups.Build(this);
}
public void Reset()
{
layoutGraph = null;
tilemap = null;
}
[HideInInspector]
[SerializeField]
GridFlowModelLookups lookups = new GridFlowModelLookups();
public FlowTilemapCell GetTilemapCell(Vector3 worldPosition)
{
var tileCoord = WorldPositionToTilemapCoord(worldPosition);
return tilemap.Cells.GetCell(tileCoord.x, tileCoord.y);
}
public FlowLayoutGraphNode GetLayoutNode(Vector3 worldPosition)
{
if (lookups == null) return null;
var tile = GetTilemapCell(worldPosition);
if (tile == null) return null;
var nodeCoord = tile.NodeCoord;
if (!lookups.NodeCoordLookup.ContainsKey(nodeCoord))
{
return null;
}
var nodeIndex = lookups.NodeCoordLookup[nodeCoord];
return (nodeIndex >= 0 && nodeIndex < layoutGraph.Nodes.Count)
? layoutGraph.Nodes[nodeIndex]
: null;
}
public GridFlowLayoutNodeRoomType GetRoomType(Vector3 worldPosition)
{
var layoutNode = GetLayoutNode(worldPosition);
if (layoutNode != null)
{
var domainData = layoutNode.GetDomainData<GridFlowTilemapDomainData>();
if (domainData != null)
{
return domainData.RoomType;
}
}
return GridFlowLayoutNodeRoomType.Unknown;
}
public IntVector2 WorldPositionToTilemapCoord(Vector3 worldPosition)
{
var basePosition = transform.position;
var localWorld = worldPosition - basePosition;
var localTileF = MathUtils.Divide(localWorld, gridSize);
return new IntVector2(
Mathf.FloorToInt(localTileF.x),
Mathf.FloorToInt(localTileF.z));
}
}
[System.Serializable]
public class GridFlowModelLookups : ISerializationCallbackReceiver
{
public Dictionary<IntVector2, int> NodeCoordLookup { get; } = new Dictionary<IntVector2, int>();
public void Build(GridFlowDungeonModel model)
{
for (var i = 0; i < model.LayoutGraph.Nodes.Count; i++)
{
var node = model.LayoutGraph.Nodes[i];
var coord = new IntVector2(
Mathf.RoundToInt(node.coord.x),
Mathf.RoundToInt(node.coord.y));
NodeCoordLookup[coord] = i;
}
}
#region Serialization
[System.Serializable]
struct SerializedNodeLookup
{
public IntVector2 coord;
public int index;
}
[SerializeField]
private SerializedNodeLookup[] serializedNodeCoordLookup;
public void OnBeforeSerialize()
{
var serializedNodeLookupList = new List<SerializedNodeLookup>();
foreach (var entry in NodeCoordLookup)
{
var lookup = new SerializedNodeLookup();
lookup.coord = entry.Key;
lookup.index = entry.Value;
serializedNodeLookupList.Add(lookup);
}
serializedNodeCoordLookup = serializedNodeLookupList.ToArray();
}
public void OnAfterDeserialize()
{
NodeCoordLookup.Clear();
if (serializedNodeCoordLookup != null)
{
foreach (var lookup in serializedNodeCoordLookup)
{
NodeCoordLookup[lookup.coord] = lookup.index;
}
}
}
#endregion
}
}