Skip to content
4 changes: 3 additions & 1 deletion Assets/Warlander/Deedplanner/Data/DataLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ private void LoadGrounds(XmlDocument document)
TextureReference tex3d = null;
List<string[]> categories = new List<string[]>();
bool diagonal = false;
bool caveDoor = false;

foreach (XmlElement child in element)
{
Expand All @@ -187,6 +188,7 @@ private void LoadGrounds(XmlDocument document)
break;
case "category":
categories.Add(child.InnerText.Split('/'));
caveDoor = (child.InnerText == "Cave doors") ? true : false;
break;
case "diagonal":
diagonal = true;
Expand All @@ -199,7 +201,7 @@ private void LoadGrounds(XmlDocument document)
Debug.LogWarning("No textures loaded, aborting");
}

GroundData data = new GroundData(name, shortName, categories.ToArray(), tex2d, tex3d, diagonal);
GroundData data = new GroundData(name, shortName, categories.ToArray(), tex2d, tex3d, diagonal, caveDoor);
Database.Grounds[shortName] = data;
Debug.Log("Ground data " + name + " loaded and ready to use!");
}
Expand Down
7 changes: 7 additions & 0 deletions Assets/Warlander/Deedplanner/Data/Grounds/DoorOrientation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Warlander.Deedplanner.Data.Grounds
{
public enum DoorOrientation
{
N, E, S, W
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Assets/Warlander/Deedplanner/Data/Grounds/Ground.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public RoadDirection RoadDirection {
get => roadDirection;
set => Tile.Map.CommandManager.AddToActionAndExecute(new RoadDirectionChangeCommand(this, roadDirection, value));
}

public Ground(Tile tile, GroundData data)
{
Tile = tile;
Expand Down
4 changes: 3 additions & 1 deletion Assets/Warlander/Deedplanner/Data/Grounds/GroundData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@ public class GroundData
public TextureReference Tex3d { get; }

public bool Diagonal { get; }
public bool IsCaveDoor { get; }

public GroundData(string name, string shortName, string[][] categories, TextureReference tex2d, TextureReference tex3d, bool diagonal)
public GroundData(string name, string shortName, string[][] categories, TextureReference tex2d, TextureReference tex3d, bool diagonal, bool isCaveDoor)
{
Name = name;
ShortName = shortName;
Categories = categories;
Tex2d = tex2d;
Tex3d = tex3d;
Diagonal = diagonal;
IsCaveDoor = isCaveDoor;
}

public override string ToString()
Expand Down
99 changes: 92 additions & 7 deletions Assets/Warlander/Deedplanner/Data/Grounds/GroundMesh.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ public class GroundMesh : MonoBehaviour
public Mesh ColliderMesh { get; private set; }
public int Width { get; private set; }
public int Height { get; private set; }

private int[,] slopesArray;
private GroundData[,] dataArray;
private RoadDirection[,] directionsArray;
private DoorOrientation[,] doorOrientationsArray;
private Map map;

private Vector3[] renderVertices;
private Vector2[] uv2;
Expand All @@ -42,8 +44,9 @@ public class GroundMesh : MonoBehaviour
private bool needsVerticesUpdate = false;
private bool needsUvUpdate = false;

public void Initialize(int width, int height, OverlayMesh newOverlayMesh)
public void Initialize(Map map, int width, int height, OverlayMesh newOverlayMesh)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of map knowing about GroundMesh and GroundMesh about the map, but this entire part of code needs later refactor anyway so I'm ok with it for now.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree.

{
this.map = map;
gameObject.layer = LayerMasks.GroundLayer;
if (groundTexturesArray == null)
{
Expand Down Expand Up @@ -82,6 +85,7 @@ public void Initialize(int width, int height, OverlayMesh newOverlayMesh)
slopesArray = new int[Width + 1, Height + 1];
dataArray = new GroundData[Width, Height];
directionsArray = new RoadDirection[Width, Height];
doorOrientationsArray = new DoorOrientation[Width, Height];

RenderMesh = new Mesh();
RenderMesh.name = "ground render mesh";
Expand Down Expand Up @@ -376,6 +380,49 @@ public int GetSlope(int x, int y)
{
return this[x, y];
}

private void ApplyUvRotation(int x, int y, DoorOrientation doorOrientation)
{
int vertexIndex = (x * Height + y) * VerticesPerRenderTile;
Vector2[] meshUvs = RenderMesh.uv;

// Corner vectors (DoorDirection.N)
Vector2 v00 = new Vector2(0, 0);
Vector2 v10 = new Vector2(1, 0);
Vector2 v01 = new Vector2(0, 1);
Vector2 v11 = new Vector2(1, 1);
Vector2 vCenter = new Vector2(0.5f, 0.5f);

// Rotating vectors based on DoorDirection

(v00, v10, v01, v11) = (doorOrientation) switch
{
DoorOrientation.E => (v10, v11, v00, v01),
DoorOrientation.S => (v11, v01, v10, v00),
DoorOrientation.W => (v01, v00, v11, v10),
_ => (v00, v10, v01, v11),
};

// Apply vectors
meshUvs[vertexIndex] = v00;
meshUvs[vertexIndex + 1] = v01;
meshUvs[vertexIndex + 2] = vCenter;

meshUvs[vertexIndex + 3] = v01;
meshUvs[vertexIndex + 4] = v11;
meshUvs[vertexIndex + 5] = vCenter;

meshUvs[vertexIndex + 6] = v11;
meshUvs[vertexIndex + 7] = v10;
meshUvs[vertexIndex + 8] = vCenter;

meshUvs[vertexIndex + 9] = v10;
meshUvs[vertexIndex + 10] = v00;
meshUvs[vertexIndex + 11] = vCenter;

RenderMesh.uv = meshUvs;
}


public void SetSlope(int x, int y, int slope)
{
Expand Down Expand Up @@ -549,14 +596,35 @@ public void SetGroundData(int x, int y, GroundData data, RoadDirection direction
return;
}

if (dataArray[x, y] == data && directionsArray[x, y] == direction)
DoorOrientation doorOrientation = DoorOrientation.N;

if (data.IsCaveDoor)
{
Tile currentTile = map?[x, y];
if (currentTile != null)
{
doorOrientation = currentTile.CalculateDoorOrientation();
}
}

bool wasCaveDoor = dataArray[x, y] != null && dataArray[x, y].IsCaveDoor;
bool isCaveDoor = data.IsCaveDoor;
bool orientationChanged = doorOrientationsArray[x, y] != doorOrientation;;

if (dataArray[x, y] == data && directionsArray[x, y] == direction && doorOrientationsArray[x, y] == doorOrientation)
{
return;
}

dataArray[x, y] = data;
directionsArray[x, y] = direction;
doorOrientationsArray[x, y] = doorOrientation;

if ((isCaveDoor && orientationChanged) || (wasCaveDoor && !isCaveDoor))
{
ApplyUvRotation(x, y, doorOrientation);
}

UpdateUV2(x, y, true);
UpdateUV2(x - 1, y, false);
UpdateUV2(x + 1, y, false);
Expand Down Expand Up @@ -587,16 +655,33 @@ private void UpdateUV2(int x, int y, bool primaryChangedTile)
int vertexIndex = index * VerticesPerRenderTile;

RoadDirection roadDirection = directionsArray[x, y];
DoorOrientation doorOrientation = doorOrientationsArray[x, y];
Vector2Int selfCoords = new Vector2Int(x, y);

var (wOffset, nOffset, eOffset, sOffset) = (data.IsCaveDoor ? doorOrientation : DoorOrientation.N) switch
{
DoorOrientation.E => (9, 0, 3, 6),
DoorOrientation.S => (6, 9, 0, 3),
DoorOrientation.W => (3, 6, 9, 0),
_ => (0, 3, 6, 9),
};

int westSlot = vertexIndex + wOffset;
int northSlot = vertexIndex + nOffset;
int eastSlot = vertexIndex + eOffset;
int southSlot = vertexIndex + sOffset;

bool forceSelfDataWest = roadDirection.IsCenter() || roadDirection.IsWest();
UpdateUV2Triangle(selfCoords, new Vector2Int(x - 1, y), vertexIndex, primaryChangedTile, forceSelfDataWest);
UpdateUV2Triangle(selfCoords, new Vector2Int(x - 1, y), westSlot, primaryChangedTile, forceSelfDataWest);

bool forceSelfDataNorth = roadDirection.IsCenter() || roadDirection.IsNorth();
UpdateUV2Triangle(selfCoords, new Vector2Int(x, y + 1), vertexIndex + 3, primaryChangedTile, forceSelfDataNorth);
UpdateUV2Triangle(selfCoords, new Vector2Int(x, y + 1), northSlot, primaryChangedTile, forceSelfDataNorth);

bool forceSelfDataEast = roadDirection.IsCenter() || roadDirection.IsEast();
UpdateUV2Triangle(selfCoords, new Vector2Int(x + 1, y), vertexIndex + 6, primaryChangedTile, forceSelfDataEast);
UpdateUV2Triangle(selfCoords, new Vector2Int(x + 1, y), eastSlot, primaryChangedTile, forceSelfDataEast);

bool forceSelfDataSouth = roadDirection.IsCenter() || roadDirection.IsSouth();
UpdateUV2Triangle(selfCoords, new Vector2Int(x, y - 1), vertexIndex + 9, primaryChangedTile, forceSelfDataSouth);
UpdateUV2Triangle(selfCoords, new Vector2Int(x, y - 1), southSlot, primaryChangedTile, forceSelfDataSouth);
}

private void UpdateUV2Triangle(Vector2Int selfCoords, Vector2Int diagonalCoords, int uvIndex, bool primaryChangedTile, bool forceSelfData)
Expand Down
2 changes: 1 addition & 1 deletion Assets/Warlander/Deedplanner/Data/Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ private void PreInitialize(int width, int height)

GameObject groundObject = new GameObject("Ground Mesh", typeof(GroundMesh));
Ground = groundObject.GetComponent<GroundMesh>();
Ground.Initialize(width, height, surfaceOverlayMesh);
Ground.Initialize(this, width, height, surfaceOverlayMesh);
surfaceOverlayMesh.Initialize(Ground.ColliderMesh);
AddEntityToMap(groundObject, 0);

Expand Down
54 changes: 51 additions & 3 deletions Assets/Warlander/Deedplanner/Data/Tile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,45 @@ public Tile(Map map, int x, int y, IOutlineCoordinator outlineCoordinator)
// Map.AddEntityToMap(caveObject, -1);
// Cave.Initialize(this, Database.DefaultCaveData);
}

public DoorOrientation CalculateDoorOrientation()
{
if (X <= 0 || X + 1 >= Map.Width || Y <= 0 || Y + 1 >= Map.Height) return DoorOrientation.N;

Tile nwTile = this.Map[X, Y + 1];
Tile neTile = this.Map[X + 1, Y + 1];
Tile seTile = this.Map[X + 1, Y];

if (nwTile == null || neTile == null || seTile == null) return DoorOrientation.N;

int sw = SurfaceHeight;
int nw = this.Map[X, Y + 1].SurfaceHeight;
int ne = this.Map[X + 1, Y + 1].SurfaceHeight;
int se = this.Map[X + 1, Y].SurfaceHeight;

float northAvg = (nw + ne) / 2f;
float eastAvg = (ne + se) / 2f;
float southAvg = (se + sw) / 2f;
float westAvg = (sw + nw) / 2f;

float max = Mathf.Max(northAvg, eastAvg, southAvg, westAvg);

if (max == northAvg) return DoorOrientation.N;
if (max == eastAvg) return DoorOrientation.E;
if (max == southAvg) return DoorOrientation.S;
if (max == westAvg) return DoorOrientation.W;

return DoorOrientation.N;
}

public void RefreshDoorOrientation()
{
if (Ground.Data.IsCaveDoor)
{
Map.Ground.SetGroundData(X, Y, Ground.Data, Ground.RoadDirection);
}
}

public void PasteTile(Tile otherTile)
{
SurfaceHeight = otherTile.SurfaceHeight;
Expand Down Expand Up @@ -1089,10 +1127,20 @@ public void Undo()
private void Refresh()
{
tile.Map.Ground.SetSlope(tile.X, tile.Y, tile.surfaceHeight);

Tile t10 = tile.Map.GetRelativeTile(tile, -1, 0);
Tile t01 = tile.Map.GetRelativeTile(tile, 0, -1);
Tile t11 = tile.Map.GetRelativeTile(tile, -1, -1);

tile.RefreshSurfaceEntities();
tile.Map.GetRelativeTile(tile, -1, 0)?.RefreshSurfaceEntities();
tile.Map.GetRelativeTile(tile, 0, -1)?.RefreshSurfaceEntities();
tile.Map.GetRelativeTile(tile, -1, -1)?.RefreshSurfaceEntities();
t10?.RefreshSurfaceEntities();
t01?.RefreshSurfaceEntities();
t11?.RefreshSurfaceEntities();

tile.RefreshDoorOrientation();
t10?.RefreshDoorOrientation();
t01?.RefreshDoorOrientation();
t11?.RefreshDoorOrientation();

tile.Map.RecalculateSurfaceHeight(tile.X, tile.Y);
}
Expand Down