mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Add tile edge rendering support (#3613)
This commit is contained in:
@@ -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);
|
||||
|
||||
119
Robust.Client/Map/TileEdgeOverlay.cs
Normal file
119
Robust.Client/Map/TileEdgeOverlay.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user