209 lines
8.4 KiB
C#
Raw Permalink Normal View History

2024-02-20 18:39:12 +08:00
using HPJ.Simulation;
using HPJ.Simulation.Enums;
using HPJ.Simulation.Map;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace HPJ.Presentation.Obstacle
{
public class NavigationObstacleSimpleSquare : NavigationObstacle
{
#region Unity
// Start is called before the first frame update
public override void Start()
{
if (!NavigationManager.Instance.Initialized)
{
Invoke(nameof(Start), 01f);
return;
}
MapTileRelationships = new Dictionary<MapSet, MapObstacleRelationshipData>();
_previousPositionRect = new PositionSquareRect(Vector3.one * 1000, _obstacleSize);
_newPositionRect = new PositionSquareRect(transform.position, _obstacleSize);
base.Start();
}
public virtual void OnDrawGizmosSelected()
{
PositionSquareRect obstacleRect = new PositionSquareRect(transform.position, _obstacleSize);
Gizmos.color = Color.red;
for (int i = 1; i < obstacleRect.Corners.Length; i++)
{
Gizmos.DrawLine(obstacleRect.Corners[i], obstacleRect.Corners[i - 1]);
}
Gizmos.DrawLine(obstacleRect.Corners[0], obstacleRect.Corners[3]);
Gizmos.color = Color.blue;
Gizmos.DrawLine(transform.position, transform.position - Vector3.up * _checkMapHeight);
}
#endregion
#region Obstacle
/// <summary>
/// Revalidate Tiles
/// </summary>
public override void RevalidateTiles()
{
foreach (MapObstacleRelationshipData Data in MapTileRelationships.Values)
{
Data.Revalidate();
}
}
/// <summary>
/// The size of the obstacle in the x and z world directions
/// </summary>
[SerializeField]
private Vector2 _obstacleSize = Vector2.one;
public Vector2 ObstacleSize { get { return _obstacleSize; } set { _obstacleSize = value; } }
private PositionSquareRect _previousPositionRect;
private PositionSquareRect _newPositionRect;
/// <summary>
/// Checks to see if the new position changes and if so it changes the mesh to block out the new corresponding tiles
/// </summary>
/// <param name="NewPosition"></param>
/// <param name="ForceCheck"></param>
public override void UpdatePosition(Vector3 NewPosition, bool ForceCheck = false)
{
if (!NavigationManager.Instance.Initialized)
{
return;
}
if (_previousPositionRect.Position != NewPosition || ForceCheck)
{
_newPositionRect.UpdatePosition(NewPosition);
// No need to update if no tiles need updating
if (PositionChanged(NewPosition))
{
_previousPositionRect.UpdatePosition(NewPosition);
foreach (MapObstacleRelationshipData Data in MapTileRelationships.Values)
{
Data.UnvalidateTiles();
}
foreach (MapSet Set in NavigationManager.Instance.MapSets)
{
if (!NavigationManager.Instance.RectOnMap(Set, _newPositionRect, _checkMapHeight))
{
continue;
}
MapObstacleRelationshipData RelationshipData;
if (MapTileRelationships.ContainsKey(Set))
{
RelationshipData = MapTileRelationships[Set];
}
else
{
RelationshipData = new MapObstacleRelationshipData(Set, this, _obstacleTileType);
MapTileRelationships.Add(Set, RelationshipData);
}
IntVector2 HigherBound = Set.GetMapTileIndex(NavigationManager.Instance.GetTileWorldPosition(_newPositionRect.Corners[0]));
IntVector2 LowerBound = Set.GetMapTileIndex(NavigationManager.Instance.GetTileWorldPosition(_newPositionRect.Corners[2]));
for (int x = LowerBound.x; x <= HigherBound.x; x++)
{
for (int y = LowerBound.y; y <= HigherBound.y; y++)
{
if (Set.GetTileType(x, y) != TileTypes.OutOfBounds)
{
//Debug.Log("Change Tile");
IntVector3 TileKey = new IntVector3(x, y, Set.InstanceID);
RelationshipData.AddOrValidateTile(TileKey);
}
}
}
}
foreach (MapObstacleRelationshipData Data in MapTileRelationships.Values)
{
ChangeMapJob GeneratedMapChangeJob = Data.GenerateMapChangeJob();
if (GeneratedMapChangeJob != null)
{
//Debug.Log("Change Map From Job");
Data.Map.ChangeMap(GeneratedMapChangeJob);
}
Data.SortRelatedTileData();
}
}
}
else
{
RevalidateTiles();
}
}
/// <summary>
/// What happens the the obstacle mesh position changes
/// </summary>
/// <param name="NewPosition"></param>
/// <returns></returns>
protected override bool PositionChanged(Vector3 NewPosition)
{
return true;
foreach (MapSet set in NavigationManager.Instance.MapSets)
{
// Find out which maps this Obstacle is on. And if the change in position was enough to change the map
for (int i = 0; i < _newPositionRect.Corners.Length; i++)
{
// Did the height change effect the map that it should previously had not
IntVector3 NewTileWorldPosition = NavigationManager.Instance.GetTileWorldPosition(_newPositionRect.Corners[i]);
IntVector3 PreviousTileWorldPosition = NavigationManager.Instance.GetTileWorldPosition(_previousPositionRect.Corners[i]);
if (_newPositionRect.Corners[i].y - set.SetSettings.MapSettings.Offset.y / 100 <= _checkMapHeight && set.PointInMap(NewTileWorldPosition))
{
if (!set.PointInMap(PreviousTileWorldPosition) || _previousPositionRect.Corners[i].y - set.SetSettings.MapSettings.Offset.y / 100f > _checkMapHeight)
{
return true;
}
if (set.GetMapTileIndex(PreviousTileWorldPosition) != set.GetMapTileIndex(NewTileWorldPosition))
{
return true;
}
}
else if (_previousPositionRect.Corners[i].y - set.SetSettings.MapSettings.Offset.y / 100f <= _checkMapHeight && set.PointInMap(PreviousTileWorldPosition))
{
return true;
}
}
}
return false;
}
protected Quaternion _previousRotation = Quaternion.identity;
/// <summary>
/// Rotates the obstacle based on the desired Rotation. Basic NavigationObstacle will only swap the object size x and y values. Inherit to ovverride this behaviour
/// </summary>
/// <param name="Rotation"></param>
public override void Rotate(Quaternion Rotation)
{
// Can use that later for more complex rotations. This Rotate just rotates 90* every time you ask this
//if (Rotation == _previousRotation)
//{
// return;
//}
if (_obstacleSize.y == _obstacleSize.x)
{
return;
}
_previousRotation = Rotation;
_obstacleSize = new Vector2(_obstacleSize.y, _obstacleSize.x);
_newPositionRect.UpdateSize(_obstacleSize);
UpdatePosition(transform.position, true);
}
#endregion
}
}