Implement map text (#28705)
This commit is contained in:
20
Content.Client/MapText/MapTextComponent.cs
Normal file
20
Content.Client/MapText/MapTextComponent.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Content.Shared.MapText;
|
||||
using Robust.Client.Graphics;
|
||||
|
||||
namespace Content.Client.MapText;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class MapTextComponent : SharedMapTextComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// The font that gets cached on component init or state changes
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public VectorFont? CachedFont;
|
||||
|
||||
/// <summary>
|
||||
/// The text currently being displayed. This is either <see cref="SharedMapTextComponent.Text"/> or the
|
||||
/// localized text <see cref="SharedMapTextComponent.LocText"/> or
|
||||
/// </summary>
|
||||
public string CachedText = string.Empty;
|
||||
}
|
||||
85
Content.Client/MapText/MapTextOverlay.cs
Normal file
85
Content.Client/MapText/MapTextOverlay.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System.Numerics;
|
||||
using Content.Shared.MapText;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.RichText;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.MapText;
|
||||
|
||||
/// <summary>
|
||||
/// Draws map text as an overlay
|
||||
/// </summary>
|
||||
public sealed class MapTextOverlay : Overlay
|
||||
{
|
||||
private readonly IConfigurationManager _configManager;
|
||||
private readonly IEntityManager _entManager;
|
||||
private readonly IUserInterfaceManager _uiManager;
|
||||
private readonly SharedTransformSystem _transform;
|
||||
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
|
||||
|
||||
public MapTextOverlay(
|
||||
IConfigurationManager configManager,
|
||||
IEntityManager entManager,
|
||||
IUserInterfaceManager uiManager,
|
||||
SharedTransformSystem transform,
|
||||
IResourceCache resourceCache,
|
||||
IPrototypeManager prototypeManager)
|
||||
{
|
||||
_configManager = configManager;
|
||||
_entManager = entManager;
|
||||
_uiManager = uiManager;
|
||||
_transform = transform;
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (args.ViewportControl == null)
|
||||
return;
|
||||
|
||||
args.DrawingHandle.SetTransform(Matrix3x2.Identity);
|
||||
|
||||
var scale = _configManager.GetCVar(CVars.DisplayUIScale);
|
||||
|
||||
if (scale == 0f)
|
||||
scale = _uiManager.DefaultUIScale;
|
||||
|
||||
DrawWorld(args.ScreenHandle, args, scale);
|
||||
|
||||
args.DrawingHandle.UseShader(null);
|
||||
}
|
||||
|
||||
private void DrawWorld(DrawingHandleScreen handle, OverlayDrawArgs args, float scale)
|
||||
{
|
||||
if ( args.ViewportControl == null)
|
||||
return;
|
||||
|
||||
var matrix = args.ViewportControl.GetWorldToScreenMatrix();
|
||||
var query = _entManager.AllEntityQueryEnumerator<MapTextComponent>();
|
||||
|
||||
// Enlarge bounds to try prevent pop-in due to large text.
|
||||
var bounds = args.WorldBounds.Enlarged(2);
|
||||
|
||||
while(query.MoveNext(out var uid, out var mapText))
|
||||
{
|
||||
var mapPos = _transform.GetMapCoordinates(uid);
|
||||
|
||||
if (mapPos.MapId != args.MapId)
|
||||
continue;
|
||||
|
||||
if (!bounds.Contains(mapPos.Position))
|
||||
continue;
|
||||
|
||||
if (mapText.CachedFont == null)
|
||||
continue;
|
||||
|
||||
var pos = Vector2.Transform(mapPos.Position, matrix) + mapText.Offset;
|
||||
var dimensions = handle.GetDimensions(mapText.CachedFont, mapText.CachedText, scale);
|
||||
handle.DrawString(mapText.CachedFont, pos - dimensions / 2f, mapText.CachedText, scale, mapText.Color);
|
||||
}
|
||||
}
|
||||
}
|
||||
81
Content.Client/MapText/MapTextSystem.cs
Normal file
81
Content.Client/MapText/MapTextSystem.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using Content.Shared.MapText;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.RichText;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.MapText;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public sealed class MapTextSystem : SharedMapTextSystem
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
||||
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlayManager = default!;
|
||||
|
||||
private MapTextOverlay _overlay = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<MapTextComponent, ComponentStartup>(OnComponentStartup);
|
||||
SubscribeLocalEvent<MapTextComponent, ComponentHandleState>(HandleCompState);
|
||||
|
||||
_overlay = new MapTextOverlay(_configManager, EntityManager, _uiManager, _transform, _resourceCache, _prototypeManager);
|
||||
_overlayManager.AddOverlay(_overlay);
|
||||
|
||||
// TODO move font prototype to robust.shared, then use ProtoId<FontPrototype>
|
||||
DebugTools.Assert(_prototypeManager.HasIndex<FontPrototype>(SharedMapTextComponent.DefaultFont));
|
||||
}
|
||||
|
||||
private void OnComponentStartup(Entity<MapTextComponent> ent, ref ComponentStartup args)
|
||||
{
|
||||
CacheText(ent.Comp);
|
||||
// TODO move font prototype to robust.shared, then use ProtoId<FontPrototype>
|
||||
DebugTools.Assert(_prototypeManager.HasIndex<FontPrototype>(ent.Comp.FontId));
|
||||
}
|
||||
|
||||
private void HandleCompState(Entity<MapTextComponent> ent, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not MapTextComponentState state)
|
||||
return;
|
||||
|
||||
ent.Comp.Text = state.Text;
|
||||
ent.Comp.LocText = state.LocText;
|
||||
ent.Comp.Color = state.Color;
|
||||
ent.Comp.FontId = state.FontId;
|
||||
ent.Comp.FontSize = state.FontSize;
|
||||
ent.Comp.Offset = state.Offset;
|
||||
|
||||
CacheText(ent.Comp);
|
||||
}
|
||||
|
||||
private void CacheText(MapTextComponent component)
|
||||
{
|
||||
component.CachedFont = null;
|
||||
|
||||
component.CachedText = string.IsNullOrWhiteSpace(component.Text)
|
||||
? Loc.GetString(component.LocText)
|
||||
: component.Text;
|
||||
|
||||
if (!_prototypeManager.TryIndex<FontPrototype>(component.FontId, out var fontPrototype))
|
||||
{
|
||||
component.CachedText = Loc.GetString("map-text-font-error");
|
||||
component.Color = Color.Red;
|
||||
|
||||
if(_prototypeManager.TryIndex<FontPrototype>(SharedMapTextComponent.DefaultFont, out var @default))
|
||||
component.CachedFont = new VectorFont(_resourceCache.GetResource<FontResource>(@default.Path), 14);
|
||||
return;
|
||||
}
|
||||
|
||||
var fontResource = _resourceCache.GetResource<FontResource>(fontPrototype.Path);
|
||||
component.CachedFont = new VectorFont(fontResource, component.FontSize);
|
||||
}
|
||||
}
|
||||
6
Content.Server/MapText/MapTextComponent.cs
Normal file
6
Content.Server/MapText/MapTextComponent.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
using Content.Shared.MapText;
|
||||
|
||||
namespace Content.Server.MapText;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class MapTextComponent : SharedMapTextComponent;
|
||||
28
Content.Server/MapText/MapTextSystem.cs
Normal file
28
Content.Server/MapText/MapTextSystem.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Content.Shared.MapText;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Server.MapText;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public sealed class MapTextSystem : SharedMapTextSystem
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<MapTextComponent, ComponentGetState>(GetCompState);
|
||||
}
|
||||
|
||||
private void GetCompState(Entity<MapTextComponent> ent, ref ComponentGetState args)
|
||||
{
|
||||
args.State = new MapTextComponentState
|
||||
{
|
||||
Text = ent.Comp.Text,
|
||||
LocText = ent.Comp.LocText,
|
||||
Color = ent.Comp.Color,
|
||||
FontId = ent.Comp.FontId,
|
||||
FontSize = ent.Comp.FontSize,
|
||||
Offset = ent.Comp.Offset
|
||||
};
|
||||
}
|
||||
}
|
||||
51
Content.Shared/MapText/SharedMapTextComponent.cs
Normal file
51
Content.Shared/MapText/SharedMapTextComponent.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System.Numerics;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.MapText;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for displaying text in world space
|
||||
/// </summary>
|
||||
|
||||
[NetworkedComponent, Access(typeof(SharedMapTextSystem))]
|
||||
public abstract partial class SharedMapTextComponent : Component
|
||||
{
|
||||
public const string DefaultFont = "Default";
|
||||
|
||||
/// <summary>
|
||||
/// The text to display. This will override <see cref="LocText"/>.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string? Text;
|
||||
|
||||
/// <summary>
|
||||
/// The localized-id of the text that should be displayed.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public LocId LocText = "map-text-default";
|
||||
// TODO VV: LocId editing
|
||||
|
||||
[DataField]
|
||||
public Color Color = Color.White;
|
||||
|
||||
[DataField]
|
||||
public string FontId = DefaultFont;
|
||||
|
||||
[DataField]
|
||||
public int FontSize = 12;
|
||||
|
||||
[DataField]
|
||||
public Vector2 Offset = Vector2.Zero;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class MapTextComponentState : ComponentState
|
||||
{
|
||||
public string? Text { get; init;}
|
||||
public LocId LocText { get; init;}
|
||||
public Color Color { get; init;}
|
||||
public string FontId { get; init; } = default!;
|
||||
public int FontSize { get; init;}
|
||||
public Vector2 Offset { get; init;}
|
||||
}
|
||||
6
Content.Shared/MapText/SharedMapTextSystem.cs
Normal file
6
Content.Shared/MapText/SharedMapTextSystem.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Content.Shared.MapText;
|
||||
|
||||
/// <summary>
|
||||
/// This handles registering the map text overlay, caching the text font and handling component state
|
||||
/// </summary>
|
||||
public abstract class SharedMapTextSystem : EntitySystem;
|
||||
2
Resources/Locale/en-US/mapping/map-text-component.ftl
Normal file
2
Resources/Locale/en-US/mapping/map-text-component.ftl
Normal file
@@ -0,0 +1,2 @@
|
||||
map-text-default = Use VV to change the displayed text
|
||||
map-text-font-error = "Error - invalid font"
|
||||
11
Resources/Prototypes/Entities/Markers/map_text.yml
Normal file
11
Resources/Prototypes/Entities/Markers/map_text.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
- type: entity
|
||||
id: MapText
|
||||
parent: MarkerBase
|
||||
name: map text
|
||||
placement:
|
||||
mode: PlaceFree
|
||||
components:
|
||||
- type: MapText
|
||||
- type: Sprite
|
||||
state: pink
|
||||
|
||||
Reference in New Issue
Block a user