3using MPewsey.ManiaMap.Exceptions;
4using System.Collections.Generic;
6using UnityEngine.AddressableAssets;
7using UnityEngine.Events;
8using UnityEngine.ResourceManagement.AsyncOperations;
33 private string _name =
"<None>";
37 public string Name {
get => _name;
set => _name = value; }
47 private Vector2Int _size = Vector2Int.one;
51 public Vector2Int
Size {
get => _size;
set => SetSizeField(ref _size, value); }
54 private Vector3 _cellSize =
new Vector3(1, 1, 0.001f);
58 public Vector3
CellSize {
get => _cellSize;
set => _cellSize = Vector3.Max(value, 0.001f * Vector3.one); }
62 private List<ActiveCellsRow> _activeCells =
new List<ActiveCellsRow>();
66 public List<ActiveCellsRow>
ActiveCells {
get => _activeCells;
set => _activeCells = value; }
69 private UnityEvent _onInitialize =
new UnityEvent();
73 public UnityEvent
OnInitialize {
get => _onInitialize;
set => _onInitialize = value; }
76 private UnityEvent _onInitialized =
new UnityEvent();
80 public UnityEvent
OnInitialized {
get => _onInitialized;
set => _onInitialized = value; }
126 private void SetSizeField(ref Vector2Int field, Vector2Int value)
128 field = Vector2Int.Max(value, Vector2Int.one);
132 private void OnValidate()
138 private void OnDrawGizmos()
140 var activeFillColor =
new Color(0, 0, 1, 0.2f);
141 var inactiveFillColor =
new Color(1, 0, 0, 0.2f);
142 var lineColor =
new Color(0, 0, 0);
143 DrawCells(activeFillColor, lineColor,
true);
144 DrawCells(inactiveFillColor, lineColor,
false);
153 private void DrawCells(Color fillColor, Color lineColor,
bool activity)
161 for (
int j = 0; j < row.Count; j++)
163 if (row[j] == activity)
166 Gizmos.color = fillColor;
167 Gizmos.DrawCube(center, cellSize);
168 Gizmos.color = lineColor;
169 Gizmos.DrawWireCube(center, cellSize);
184 AssetReferenceGameObject prefab, Transform parent =
null,
185 bool assignLayoutPosition =
false)
187 var roomLayout = layoutPack.
Layout.Rooms[id];
188 var roomState = layoutPack.
LayoutState.RoomStates[id];
191 return InstantiateRoomAsync(prefab, parent, layoutPack, roomLayout, roomState, cellLayer, triggeringLayers, assignLayoutPosition);
205 public static AsyncOperationHandle<GameObject>
InstantiateRoomAsync(AssetReferenceGameObject prefab, Transform parent,
207 int cellLayer, LayerMask triggeringLayers,
bool assignLayoutPosition)
209 var handle = prefab.InstantiateAsync(parent);
211 handle.Completed += handle => handle.Result.GetComponent<
RoomComponent>()
212 .
Initialize(layoutPack, roomLayout, roomState, cellLayer, triggeringLayers, assignLayoutPosition);
226 bool assignLayoutPosition =
false)
228 var roomLayout = layoutPack.
Layout.Rooms[id];
229 var roomState = layoutPack.
LayoutState.RoomStates[id];
232 return InstantiateRoom(prefab, parent, layoutPack, roomLayout, roomState, cellLayer, triggeringLayers, assignLayoutPosition);
248 int cellLayer, LayerMask triggeringLayers,
bool assignLayoutPosition)
250 var room = Instantiate(prefab, parent).GetComponent<
RoomComponent>();
251 room.
Initialize(layoutPack, roomLayout, roomState, cellLayer, triggeringLayers, assignLayoutPosition);
265 int cellLayer, LayerMask triggeringLayers,
bool assignLayoutPosition)
274 if (assignLayoutPosition)
302 for (
int i = 0; i <
Rows; i++)
304 for (
int j = 0; j <
Columns; j++)
324 while (row.Values.Count >
Columns)
326 row.Values.RemoveAt(row.Values.Count - 1);
329 while (row.Values.Count <
Columns)
331 row.Values.Add(
true);
354 var startRow = Mathf.Min(startIndex.x, endIndex.x);
355 var endRow = Mathf.Max(startIndex.x, endIndex.x);
356 var startColumn = Mathf.Min(startIndex.y, endIndex.y);
357 var endColumn = Mathf.Max(startIndex.y, endIndex.y);
359 for (
int i = startRow; i <= endRow; i++)
361 for (
int j = startColumn; j <= endColumn; j++)
381 throw new System.IndexOutOfRangeException($
"Index out of range: ({row}, {column})");
397 throw new System.NotImplementedException($
"Unhandled cell activity: {activity}.");
411 throw new System.IndexOutOfRangeException($
"Index out of range: ({row}, {column})");
425 throw new System.IndexOutOfRangeException($
"Index out of range: ({row}, {column})");
437 return (uint)row < (uint)
Rows && (uint)column < (uint)
Columns;
456 var children = GetComponentsInChildren<CellChild>();
458 foreach (var child
in children)
460 child.AutoAssign(
this);
463 return children.Length;
476 return Quaternion.Euler(0, 0, 0);
478 return Quaternion.Euler(90, 0, 0);
480 throw new System.ArgumentException($
"Unhandled room type: {RoomType}.");
522 throw new System.ArgumentException($
"Unhandled room type: {RoomType}.");
537 return new Vector3(gridPosition.x, -gridPosition.y, -gridPosition.z);
539 return new Vector3(gridPosition.x, gridPosition.z, -gridPosition.y);
541 throw new System.ArgumentException($
"Unhandled room type: {RoomType}.");
556 return new Vector3(localPosition.x, -localPosition.y, -localPosition.z);
558 return new Vector3(localPosition.x, -localPosition.z, localPosition.y);
560 throw new System.ArgumentException($
"Unhandled room type: {RoomType}.");
611 var row = Mathf.FloorToInt(position.y /
CellSize.y);
612 var column = Mathf.FloorToInt(position.x /
CellSize.x);
615 return new Vector2Int(row, column);
617 return new Vector2Int(-1, -1);
651 var
template =
new RoomTemplate(
id, name, cells, spots);
664 for (
int i = 0; i < cells.Rows; i++)
666 for (
int j = 0; j < cells.Columns; j++)
669 cells[i, j] = Cell.New;
682 foreach (var door
in GetComponentsInChildren<DoorComponent>())
684 var cell = cells[door.Row, door.Column];
685 cell.SetDoor(door.Direction, door.GetMMDoor());
695 foreach (var feature
in GetComponentsInChildren<Feature>())
697 var cell = cells[feature.Row, feature.Column];
698 cell.AddFeature(feature.Name);
707 var spots = GetComponentsInChildren<CollectableSpotComponent>();
708 var result =
new Dictionary<int, CollectableSpot>(spots.Length);
710 foreach (var spot
in spots)
712 result.Add(spot.Id, spot.GetMMCollectableSpot());
724 var
set =
new HashSet<int>();
726 foreach (var flag
in GetComponentsInChildren<RoomFlag>())
728 if (!
set.Add(flag.Id))
729 throw new DuplicateIdException($
"Duplicate room flag ID {flag.Id} for object {flag}.");
744 var index = Vector2Int.zero;
745 var minDistance =
float.PositiveInfinity;
748 for (
int i = 0; i <
Rows; i++)
750 for (
int j = 0; j <
Columns; j++)
755 var distance = delta.sqrMagnitude;
757 if (distance < minDistance)
759 minDistance = distance;
760 index =
new Vector2Int(i, j);
777 System.Span<DoorDirection> directions = stackalloc DoorDirection[]
784 DoorDirection.Bottom,
787 System.Span<Vector3> vectors = stackalloc Vector3[]
789 new Vector3(0, -1, 0),
790 new Vector3(1, 0, 0),
791 new Vector3(0, 1, 0),
792 new Vector3(-1, 0, 0),
793 new Vector3(0, 0, 1),
794 new Vector3(0, 0, -1),
798 var maxDistance =
float.NegativeInfinity;
805 for (
int i = 0; i < count; i++)
807 var distance = Vector3.Dot(delta, vectors[i]);
809 if (distance > maxDistance)
811 maxDistance = distance;
816 return directions[index];
The base class for cell trigger areas.
static CellArea InstantiateCellArea(int row, int column, RoomComponent room, int cellLayer, LayerMask triggeringLayers)
Instantiates a new cell area within the specified room.
A manager for maintaining the current map data and state.
LayoutState LayoutState
The layout state.
ManiaMapSettings Settings
The applied settings.
LayerMask TriggeringLayers
The physics layers that trigger room cell area triggers.
int CellLayer
The physics layer assigned to room cell area triggers.
A component for creating a room.
Vector3 GridToLocalPosition(Vector3 gridPosition)
Converts the specified grid coordinate to local coordinates.
bool CellIndexExists(int row, int column)
Returns true if the cell index exists.
Vector3 CenterGlobalPosition()
Returns the center of the cell grid in global coordinates.
Vector3 LocalCellSize()
Returns the cell size in local coordinates.
static AsyncOperationHandle< GameObject > InstantiateRoomAsync(AssetReferenceGameObject prefab, Transform parent, LayoutPack layoutPack, Room roomLayout, RoomState roomState, int cellLayer, LayerMask triggeringLayers, bool assignLayoutPosition)
Instantiates and initializes a room asynchronously. Returns the operation handle.
void SetCellActivity(int row, int column, bool activity)
Sets the cell activity for the specified index.
void SizeActiveCells()
Sizes the active cells list to match the room size.
int AutoAssign()
Runs auto assign on the room's cell children. Returns the number of children.
Vector2Int GridPositionToCellIndex(Vector3 position)
Converts the specified grid position to the containing cell index. If the cell index does not exist,...
void MoveToLayoutPosition()
Sets the room's local position to its position in the layout.
static RoomComponent InstantiateRoom(GameObject prefab, Transform parent, LayoutPack layoutPack, Room roomLayout, RoomState roomState, int cellLayer, LayerMask triggeringLayers, bool assignLayoutPosition)
Instantiates and initializes a room and returns it.
Room RoomLayout
The room data.
bool Initialize(LayoutPack layoutPack, Room roomLayout, RoomState roomState, int cellLayer, LayerMask triggeringLayers, bool assignLayoutPosition)
Initializes the room. Returns false if the room has already been initialized.
UnityEvent OnInitialize
An event invoked when the room is initialized.
Vector2Int GlobalPositionToCellIndex(Vector3 position)
Converts the specified global position to the containing cell index. If the cell index does not exist...
Vector3 CenterLocalPosition()
Returns the center of the cell grid in local coordinates.
Array2D< Cell > GetMMCells()
Returns the Mania Map cells used by the procedural generator.
Dictionary< int, CollectableSpot > GetMMCollectableSpots()
Returns the Mania Map collectable spots by ID.
Vector2Int LocalPositionToCellIndex(Vector3 position)
Converts the specified local position to the containing cell index. If the cell index does not exist,...
Vector3 LocalToGridPosition(Vector3 localPosition)
Converts the specified local coordinate to grid coordinates.
static RoomComponent InstantiateRoom(Uid id, LayoutPack layoutPack, GameObject prefab, Transform parent=null, bool assignLayoutPosition=false)
Instantiates and initializes a room and returns it.
Vector3 CellCenterGridPosition(int row, int column)
Returns the cell center for the specified index in grid coordinates.
UnityEvent OnInitialized
The event invoked after the room has completed initialization.
Vector3 CellCenterLocalPosition(int row, int column)
Returns the cell center for the specified index in local coordinates.
string Name
The room name.
void AddMMFeatures(Array2D< Cell > cells)
Adds the cell features to the cells array.
Vector2Int Size
The size of the room grid in rows (x) and columns (y).
void AddMMDoors(Array2D< Cell > cells)
Adds the Mania Map doors to the cells array.
Vector3 CellSize
The size of each cell within the grid coordinate system.
bool CellIndexRangeExists(Vector2Int startIndex, Vector2Int endIndex)
Returns true if both cell indexes exist.
RoomTemplateResource RoomTemplate
The room template.
void DrawCells(Color fillColor, Color lineColor, bool activity)
Draws the cell cube gizmos for the specified cell activity.
void ValidateRoomFlags()
Validates that the room flag ID's are unique.
DoorDirection FindClosestDoorDirection(int row, int column, Vector3 position)
Returns the closest door direction based on the specified global position.
CellAreaTriggerEvent OnCellAreaEntered
The event invoked when a room cell has been entered. Message includes the enterered cell and the coll...
Vector3 CenterGridPosition()
Returns the center of the cell grid in grid coordinates.
RoomState RoomState
The room state.
bool SetCellActivities(Vector2Int startIndex, Vector2Int endIndex, CellActivity activity)
Sets the cell activities for the specified index range. No action is taken if one of the indexes is o...
void SetCellActivity(int row, int column, CellActivity activity)
Sets the cell activity for the specified index.
Vector2Int FindClosestActiveCellIndex(Vector3 position)
Returns the closest active cell index for the specified global position.
int Columns
The column index.
bool IsInitialized
True if the room has been initialized.
Quaternion GetCellViewDirection()
Returns the quaternion angle perpendicular to the cell plane.
RoomTemplate GetMMRoomTemplate(int id, string name)
Returns the Mania Map room template used by the procedural generator.
List< ActiveCellsRow > ActiveCells
A list of active cell rows.
CellAreaTriggerEvent OnCellAreaExited
The event invoked when a room cell has been exited. Message includes the exited cell and the collidin...
Vector3 GlobalToGridPosition(Vector3 globalPosition)
Converts the specified global position to grid coordinates.
Vector3 CellCenterGlobalPosition(int row, int column)
Returns the cell center for the specified index in global coordinates.
bool GetCellActivity(int row, int column)
Returns the cell activity for the specified index.
void CreateCellAreas(int cellLayer, LayerMask triggeringLayers)
Creates the cell area triggers as children of the room.
static AsyncOperationHandle< GameObject > InstantiateRoomAsync(Uid id, LayoutPack layoutPack, AssetReferenceGameObject prefab, Transform parent=null, bool assignLayoutPosition=false)
Instantiates and initializes a room asynchronously. Returns the operation handle.
A container for storing a serialized room template.
CellActivity
The cell activity.
RoomType
The type of room.
The row of the RoomComponent active cells list.