|
2 | 2 | using OpenDreamClient.Interface; |
3 | 3 | using Robust.Client.Graphics; |
4 | 4 | using Robust.Client.Player; |
5 | | -using Robust.Shared.Enums; |
6 | 5 | using Robust.Shared.Map; |
7 | 6 | using OpenDreamShared.Dream; |
8 | 7 | using Robust.Shared.Console; |
|
13 | 12 | using Robust.Shared.Profiling; |
14 | 13 | using Vector3 = Robust.Shared.Maths.Vector3; |
15 | 14 | using Matrix3x2 = System.Numerics.Matrix3x2; |
| 15 | +using Robust.Client.ResourceManagement; |
| 16 | +using Robust.Shared.Enums; |
16 | 17 |
|
17 | 18 | namespace OpenDreamClient.Rendering; |
18 | 19 |
|
@@ -40,6 +41,9 @@ internal sealed class DreamViewOverlay : Overlay { |
40 | 41 | [Dependency] private readonly IClyde _clyde = default!; |
41 | 42 | [Dependency] private readonly IPrototypeManager _protoManager = default!; |
42 | 43 | [Dependency] private readonly ProfManager _prof = default!; |
| 44 | + [Dependency] private readonly IResourceCache _resourceCache = default!; |
| 45 | + |
| 46 | + private readonly Font _defaultMaptextFont; |
43 | 47 |
|
44 | 48 | private readonly ISawmill _sawmill = Logger.GetSawmill("opendream.view"); |
45 | 49 |
|
@@ -83,6 +87,7 @@ public DreamViewOverlay(RenderTargetPool renderTargetPool, TransformSystem trans |
83 | 87 | _appearanceSystem = appearanceSystem; |
84 | 88 | _screenOverlaySystem = screenOverlaySystem; |
85 | 89 | _clientImagesSystem = clientImagesSystem; |
| 90 | + _defaultMaptextFont = new VectorFont(_resourceCache.GetResource<FontResource>("/Fonts/NotoSans-Regular.ttf"),8); |
86 | 91 |
|
87 | 92 | _spriteQuery = _entityManager.GetEntityQuery<DMISpriteComponent>(); |
88 | 93 | _xformQuery = _entityManager.GetEntityQuery<TransformComponent>(); |
@@ -338,7 +343,35 @@ private void ProcessIconComponents(DreamIcon icon, Vector2 position, EntityUid u |
338 | 343 | // TODO: vis_flags |
339 | 344 | } |
340 | 345 |
|
341 | | - //TODO maptext - note colour + transform apply |
| 346 | + //maptext is basically just an image of rendered text added as an overlay |
| 347 | + if(icon.Appearance.Maptext != null){ //if has maptext |
| 348 | + RendererMetaData maptext = RentRendererMetaData(); |
| 349 | + maptext.MainIcon = icon; |
| 350 | + maptext.Position = current.Position; |
| 351 | + maptext.Uid = current.Uid; |
| 352 | + maptext.ClickUid = current.Uid; |
| 353 | + maptext.IsScreen = current.IsScreen; |
| 354 | + tieBreaker++; |
| 355 | + maptext.TieBreaker = tieBreaker; |
| 356 | + maptext.Plane = current.Plane; |
| 357 | + maptext.Layer = current.Layer; |
| 358 | + maptext.RenderSource = null; |
| 359 | + maptext.RenderTarget = null; |
| 360 | + maptext.MouseOpacity = current.MouseOpacity; |
| 361 | + maptext.TransformToApply = current.TransformToApply; |
| 362 | + maptext.ColorToApply = current.ColorToApply; |
| 363 | + maptext.ColorMatrixToApply = current.ColorMatrixToApply; |
| 364 | + maptext.AlphaToApply = current.AlphaToApply; |
| 365 | + maptext.BlendMode = current.BlendMode; |
| 366 | + |
| 367 | + maptext.AppearanceFlags = current.AppearanceFlags; |
| 368 | + maptext.AppearanceFlags &= ~AppearanceFlags.PlaneMaster; //doesn't make sense for maptext |
| 369 | + |
| 370 | + maptext.Maptext = icon.Appearance.Maptext; |
| 371 | + maptext.MaptextSize = icon.Appearance.MaptextSize; |
| 372 | + maptext.Position += icon.Appearance.MaptextOffset/(float)EyeManager.PixelsPerMeter; |
| 373 | + result.Add(maptext); |
| 374 | + } |
342 | 375 |
|
343 | 376 | //TODO particles - colour and transform don't apply? |
344 | 377 |
|
@@ -400,6 +433,11 @@ public void DrawIcon(DrawingHandleWorld handle, Vector2i renderTargetSize, Rende |
400 | 433 | positionOffset -= ((ktSize/EyeManager.PixelsPerMeter) - Vector2.One) * new Vector2(0.5f); //correct for KT group texture offset |
401 | 434 | } |
402 | 435 |
|
| 436 | + //Maptext |
| 437 | + if(iconMetaData.Maptext != null){ |
| 438 | + iconMetaData.TextureOverride = GetTextureFromMaptext(iconMetaData.Maptext, iconMetaData.MaptextSize!.Value.X, iconMetaData.MaptextSize!.Value.Y, handle); |
| 439 | + } |
| 440 | + |
403 | 441 | var frame = iconMetaData.GetTexture(this, handle); |
404 | 442 | var pixelPosition = (iconMetaData.Position + positionOffset) * EyeManager.PixelsPerMeter; |
405 | 443 |
|
@@ -756,6 +794,28 @@ private Texture ProcessKeepTogether(DrawingHandleWorld handle, RendererMetaData |
756 | 794 | return ktTexture.Texture; |
757 | 795 | } |
758 | 796 |
|
| 797 | + public Texture GetTextureFromMaptext(string maptext, int width, int height, DrawingHandleWorld handle) { |
| 798 | + if(width == 0) width = 32; |
| 799 | + if(height == 0) height = 32; |
| 800 | + IRenderTexture tempTexture = _renderTargetPool.Rent(new Vector2i(width, height)); |
| 801 | + handle.RenderInRenderTarget(tempTexture, () => { |
| 802 | + handle.SetTransform(CreateRenderTargetFlipMatrix(tempTexture.Size, Vector2.Zero)); |
| 803 | + float scale = 1; |
| 804 | + var font = _defaultMaptextFont; |
| 805 | + var baseLine = new Vector2(0, 0); |
| 806 | + foreach (var rune in maptext.EnumerateRunes()){ |
| 807 | + var metric = font.GetCharMetrics(rune, scale); |
| 808 | + Vector2 mod = new Vector2(0); |
| 809 | + if(metric.HasValue) |
| 810 | + mod.Y += metric.Value.BearingY - (metric.Value.Height - metric.Value.BearingY); |
| 811 | + |
| 812 | + baseLine.X += font.DrawChar(handle, rune, baseLine+mod, scale, Color.White); |
| 813 | + } |
| 814 | + }, Color.Transparent); |
| 815 | + _renderTargetPool.ReturnAtEndOfFrame(tempTexture); |
| 816 | + return tempTexture.Texture; |
| 817 | + } |
| 818 | + |
759 | 819 | /// <summary> |
760 | 820 | /// Creates a transformation matrix that counteracts RT's |
761 | 821 | /// <see cref="DrawingHandleBase.RenderInRenderTarget(IRenderTarget,Action,System.Nullable{Robust.Shared.Maths.Color})"/> quirks |
@@ -812,6 +872,8 @@ internal sealed class RendererMetaData : IComparable<RendererMetaData> { |
812 | 872 | public BlendMode BlendMode; |
813 | 873 | public MouseOpacity MouseOpacity; |
814 | 874 | public Texture? TextureOverride; |
| 875 | + public string? Maptext; |
| 876 | + public Vector2i? MaptextSize; |
815 | 877 |
|
816 | 878 | public bool IsPlaneMaster => (AppearanceFlags & AppearanceFlags.PlaneMaster) != 0; |
817 | 879 | public bool HasRenderSource => !string.IsNullOrEmpty(RenderSource); |
@@ -841,6 +903,8 @@ public void Reset() { |
841 | 903 | BlendMode = BlendMode.Default; |
842 | 904 | MouseOpacity = MouseOpacity.Transparent; |
843 | 905 | TextureOverride = null; |
| 906 | + Maptext = null; |
| 907 | + MaptextSize = null; |
844 | 908 | } |
845 | 909 |
|
846 | 910 | public Texture? GetTexture(DreamViewOverlay viewOverlay, DrawingHandleWorld handle) { |
|
0 commit comments