Add tile edge rendering support (#3613)

This commit is contained in:
metalgearsloth
2023-03-05 12:16:53 +11:00
committed by GitHub
parent e56501649b
commit 7521ed060b
4 changed files with 233 additions and 1 deletions

View File

@@ -1,4 +1,10 @@
using Robust.Client.Graphics;
using Robust.Client.Map;
using Robust.Client.Physics;
using Robust.Client.ResourceManagement;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Dynamics;
@@ -6,6 +12,23 @@ namespace Robust.Client.GameObjects
{
public sealed class MapSystem : SharedMapSystem
{
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IOverlayManager _overlayManager = default!;
[Dependency] private readonly IResourceCache _resource = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
public override void Initialize()
{
base.Initialize();
_overlayManager.AddOverlay(new TileEdgeOverlay(EntityManager, _mapManager, _resource, _tileDefinitionManager));
}
public override void Shutdown()
{
base.Shutdown();
_overlayManager.RemoveOverlay<TileEdgeOverlay>();
}
protected override void OnMapAdd(EntityUid uid, MapComponent component, ComponentAdd args)
{
EnsureComp<PhysicsMapComponent>(uid);

View File

@@ -0,0 +1,119 @@
using System;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.Enums;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Maths;
namespace Robust.Client.Map;
/// <summary>
/// Draws border sprites for tiles that support them.
/// </summary>
public sealed class TileEdgeOverlay : Overlay
{
private readonly IEntityManager _entManager;
private readonly IMapManager _mapManager;
private readonly IResourceCache _resource;
private readonly ITileDefinitionManager _tileDefManager;
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowEntities;
public TileEdgeOverlay(IEntityManager entManager, IMapManager mapManager, IResourceCache resource, ITileDefinitionManager tileDefManager)
{
_entManager = entManager;
_mapManager = mapManager;
_resource = resource;
_tileDefManager = tileDefManager;
ZIndex = -1;
}
protected internal override void Draw(in OverlayDrawArgs args)
{
if (args.MapId == MapId.Nullspace)
return;
var xformQuery = _entManager.GetEntityQuery<TransformComponent>();
foreach (var grid in _mapManager.FindGridsIntersecting(args.MapId, args.WorldBounds))
{
var tileSize = grid.TileSize;
var tileDimensions = new Vector2(tileSize, tileSize);
var xform = xformQuery.GetComponent(grid.Owner);
args.WorldHandle.SetTransform(xform.WorldMatrix);
foreach (var tileRef in grid.GetTilesIntersecting(args.WorldBounds, false))
{
var tileDef = _tileDefManager[tileRef.Tile.TypeId];
if (tileDef.EdgeSprites.Count == 0)
continue;
// Get what tiles border us to determine what sprites we need to draw.
for (var x = -1; x <= 1; x++)
{
for (var y = -1; y <= 1; y++)
{
if (x == 0 && y == 0)
continue;
var neighborIndices = new Vector2i(tileRef.GridIndices.X + x, tileRef.GridIndices.Y + y);
var neighborTile = grid.GetTileRef(neighborIndices);
// If it's the same tile then no edge to be drawn.
if (tileRef.Tile.TypeId == neighborTile.Tile.TypeId)
continue;
var direction = new Vector2i(x, y).AsDirection();
// No edge tile
if (!tileDef.EdgeSprites.TryGetValue(direction, out var edgePath))
continue;
var texture = _resource.GetResource<TextureResource>(edgePath);
var box = Box2.FromDimensions(neighborIndices, tileDimensions);
var angle = Angle.Zero;
// If we ever need one for both cardinals and corners then update this.
switch (direction)
{
// Corner sprites
case Direction.SouthEast:
break;
case Direction.NorthEast:
angle = new Angle(MathF.PI / 2f);
break;
case Direction.NorthWest:
angle = new Angle(MathF.PI);
break;
case Direction.SouthWest:
angle = new Angle(MathF.PI * 1.5f);
break;
// Edge sprites
case Direction.South:
break;
case Direction.East:
angle = new Angle(MathF.PI / 2f);
break;
case Direction.North:
angle = new Angle(MathF.PI);
break;
case Direction.West:
angle = new Angle(MathF.PI * 1.5f);
break;
}
if (angle == Angle.Zero)
args.WorldHandle.DrawTextureRect(texture, box);
else
args.WorldHandle.DrawTextureRect(texture, new Box2Rotated(box, angle, box.Center));
}
}
}
}
args.WorldHandle.SetTransform(Matrix3.Identity);
}
}

View File

@@ -87,6 +87,89 @@ namespace Robust.Shared.Maths
}
}
public static DirectionFlag AsDirectionFlag(this Vector2i indices)
{
switch (indices.X)
{
case -1:
switch (indices.Y)
{
case -1:
return DirectionFlag.SouthWest;
case 0:
return DirectionFlag.West;
case 1:
return DirectionFlag.NorthWest;
}
break;
case 0:
switch (indices.Y)
{
case -1:
return DirectionFlag.South;
case 1:
return DirectionFlag.North;
}
break;
case 1:
switch (indices.Y)
{
case -1:
return DirectionFlag.SouthEast;
case 0:
return DirectionFlag.East;
case 1:
return DirectionFlag.NorthEast;
}
break;
}
throw new ArgumentOutOfRangeException(
$"Tried to use a non-supported Vector2i for conversion to direction flag");
}
public static Direction AsDirection(this Vector2i indices)
{
switch (indices.X)
{
case -1:
switch (indices.Y)
{
case -1:
return Direction.SouthWest;
case 0:
return Direction.West;
case 1:
return Direction.NorthWest;
}
break;
case 0:
switch (indices.Y)
{
case -1:
return Direction.South;
case 1:
return Direction.North;
}
break;
case 1:
switch (indices.Y)
{
case -1:
return Direction.SouthEast;
case 0:
return Direction.East;
case 1:
return Direction.NorthEast;
}
break;
}
throw new ArgumentOutOfRangeException(
$"Tried to use a non-supported Vector2i for conversion to direction");
}
/// <summary>
/// Converts a direction vector to the closest Direction enum.
/// </summary>

View File

@@ -1,4 +1,6 @@
using Robust.Shared.Utility;
using System.Collections.Generic;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
namespace Robust.Shared.Map
{
@@ -27,6 +29,11 @@ namespace Robust.Shared.Map
/// </summary>
ResourcePath? Sprite { get; }
/// <summary>
/// Possible sprites to use if we're neighboring another tile.
/// </summary>
Dictionary<Direction, ResourcePath> EdgeSprites { get; }
/// <summary>
/// Physics objects that are interacting on this tile are slowed down by this float.
/// </summary>