mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-15 14:52:35 +02:00
394 lines
15 KiB
C#
394 lines
15 KiB
C#
using System;
|
|
using System.Runtime.InteropServices;
|
|
using Robust.Client.GameObjects;
|
|
using Robust.Client.Graphics.ClientEye;
|
|
using Robust.Client.Graphics.Drawing;
|
|
using Robust.Client.Graphics.Shaders;
|
|
using Robust.Client.Interfaces.Graphics;
|
|
using Robust.Shared.Interfaces.GameObjects;
|
|
using Robust.Shared.Maths;
|
|
|
|
namespace Robust.Client.Graphics.Clyde
|
|
{
|
|
internal partial class Clyde
|
|
{
|
|
private sealed class RenderHandle : IRenderHandle
|
|
{
|
|
private readonly Clyde _clyde;
|
|
|
|
public DrawingHandleScreen DrawingHandleScreen { get; }
|
|
public DrawingHandleWorld DrawingHandleWorld { get; }
|
|
|
|
public RenderHandle(Clyde clyde)
|
|
{
|
|
_clyde = clyde;
|
|
|
|
DrawingHandleScreen = new DrawingHandleScreenImpl(this);
|
|
DrawingHandleWorld = new DrawingHandleWorldImpl(this);
|
|
}
|
|
|
|
public void SetModelTransform(in Matrix3 matrix)
|
|
{
|
|
_clyde.DrawSetModelTransform(matrix);
|
|
}
|
|
|
|
public void SetViewTransform(in Matrix3 matrix)
|
|
{
|
|
_clyde.DrawSetViewTransform(matrix);
|
|
}
|
|
|
|
public void ResetViewTransform()
|
|
{
|
|
_clyde.DrawResetViewTransform();
|
|
}
|
|
|
|
public void DrawTexture(Texture texture, Vector2 bl, Vector2 br, Vector2 tl, Vector2 tr, Color modulate, UIBox2? subRegion)
|
|
{
|
|
if (texture is AtlasTexture atlas)
|
|
{
|
|
texture = atlas.SourceTexture;
|
|
if (subRegion.HasValue)
|
|
{
|
|
var offset = atlas.SubRegion.TopLeft;
|
|
subRegion = new UIBox2(
|
|
subRegion.Value.TopLeft + offset,
|
|
subRegion.Value.BottomRight + offset);
|
|
}
|
|
else
|
|
{
|
|
subRegion = atlas.SubRegion;
|
|
}
|
|
}
|
|
|
|
var clydeTexture = (ClydeTexture) texture;
|
|
|
|
_clyde.DrawTexture(clydeTexture.TextureId, bl, br, tl, tr, modulate, subRegion);
|
|
}
|
|
|
|
public void SetScissor(UIBox2i? scissorBox)
|
|
{
|
|
_clyde.DrawSetScissor(scissorBox);
|
|
}
|
|
|
|
public void SetSpace(CurrentSpace space)
|
|
{
|
|
_clyde.DrawSwitchSpace(space);
|
|
}
|
|
|
|
public void DrawEntity(IEntity entity, Vector2 position, Vector2 scale, Direction? overrideDirection)
|
|
{
|
|
if (entity.Deleted)
|
|
{
|
|
throw new ArgumentException("Tried to draw an entity has been deleted.", nameof(entity));
|
|
}
|
|
|
|
var sprite = entity.GetComponent<SpriteComponent>();
|
|
|
|
// Switch rendering to world space.
|
|
SetSpace(CurrentSpace.WorldSpace);
|
|
|
|
{
|
|
var ofsX = position.X - _clyde.ScreenSize.X / 2f;
|
|
var ofsY = position.Y - _clyde.ScreenSize.Y / 2f;
|
|
|
|
var viewMatrix = Matrix3.Identity;
|
|
viewMatrix.R0C0 = scale.X;
|
|
viewMatrix.R1C1 = scale.Y;
|
|
viewMatrix.R0C2 = ofsX / EyeManager.PixelsPerMeter;
|
|
viewMatrix.R1C2 = -ofsY / EyeManager.PixelsPerMeter;
|
|
|
|
SetViewTransform(viewMatrix);
|
|
}
|
|
|
|
// Draw the entity.
|
|
sprite.Render(
|
|
DrawingHandleWorld,
|
|
overrideDirection == null
|
|
? entity.Transform.WorldRotation
|
|
: Angle.Zero,
|
|
overrideDirection);
|
|
|
|
// Reset to screen space
|
|
SetSpace(CurrentSpace.ScreenSpace);
|
|
}
|
|
|
|
public void DrawLine(Vector2 a, Vector2 b, Color color)
|
|
{
|
|
_clyde.DrawLine(a, b, color);
|
|
}
|
|
|
|
public void UseShader(ShaderInstance shader)
|
|
{
|
|
if (shader != null && shader.Disposed)
|
|
{
|
|
throw new ArgumentException("Unable to use disposed shader instance.", nameof(shader));
|
|
}
|
|
|
|
var clydeShader = (ClydeShaderInstance) shader;
|
|
|
|
_clyde.DrawUseShader(clydeShader?.Handle ?? _clyde._defaultShader.Handle);
|
|
}
|
|
|
|
public void Viewport(Box2i viewport)
|
|
{
|
|
_clyde.DrawViewport(viewport);
|
|
}
|
|
|
|
public void UseRenderTarget(IRenderTarget renderTarget)
|
|
{
|
|
var target = (RenderTarget) renderTarget;
|
|
|
|
_clyde.DrawRenderTarget(target?.Handle ?? default);
|
|
}
|
|
|
|
public void Clear(Color color)
|
|
{
|
|
_clyde.DrawClear(color);
|
|
}
|
|
|
|
public void DrawPrimitives(DrawPrimitiveTopology primitiveTopology, ReadOnlySpan<Vector2> vertices, Color color)
|
|
{
|
|
// TODO: Maybe don't stackalloc if the data is too large.
|
|
Span<DrawVertexUV2D> drawVertices = stackalloc DrawVertexUV2D[vertices.Length];
|
|
PadVertices(vertices, drawVertices);
|
|
|
|
DrawPrimitives(primitiveTopology, Texture.White, drawVertices, color);
|
|
}
|
|
|
|
public void DrawPrimitives(DrawPrimitiveTopology primitiveTopology, ReadOnlySpan<ushort> indices,
|
|
ReadOnlySpan<Vector2> vertices, Color color)
|
|
{
|
|
// TODO: Maybe don't stackalloc if the data is too large.
|
|
Span<DrawVertexUV2D> drawVertices = stackalloc DrawVertexUV2D[vertices.Length];
|
|
PadVertices(vertices, drawVertices);
|
|
|
|
DrawPrimitives(primitiveTopology, Texture.White, indices, drawVertices, color);
|
|
}
|
|
|
|
public void DrawPrimitives(DrawPrimitiveTopology primitiveTopology, Texture texture,
|
|
ReadOnlySpan<DrawVertexUV2D> vertices, Color color)
|
|
{
|
|
if (!(texture is ClydeTexture clydeTexture))
|
|
{
|
|
throw new ArgumentException("Texture must be a basic texture.");
|
|
}
|
|
|
|
var castSpan = MemoryMarshal.Cast<DrawVertexUV2D, Vertex2D>(vertices);
|
|
|
|
_clyde.DrawPrimitives(primitiveTopology, clydeTexture.TextureId, castSpan, color);
|
|
}
|
|
|
|
public void DrawPrimitives(DrawPrimitiveTopology primitiveTopology, Texture texture, ReadOnlySpan<ushort> indices,
|
|
ReadOnlySpan<DrawVertexUV2D> vertices, Color color)
|
|
{
|
|
if (!(texture is ClydeTexture clydeTexture))
|
|
{
|
|
throw new ArgumentException("Texture must be a basic texture.");
|
|
}
|
|
|
|
var castSpan = MemoryMarshal.Cast<DrawVertexUV2D, Vertex2D>(vertices);
|
|
|
|
_clyde.DrawPrimitives(primitiveTopology, clydeTexture.TextureId, indices, castSpan, color);
|
|
}
|
|
|
|
private void PadVertices(ReadOnlySpan<Vector2> input, Span<DrawVertexUV2D> output)
|
|
{
|
|
for (var i = 0; i < output.Length; i++)
|
|
{
|
|
output[i] = new DrawVertexUV2D(input[i], (0.5f, 0.5f));
|
|
}
|
|
}
|
|
|
|
private sealed class DrawingHandleScreenImpl : DrawingHandleScreen
|
|
{
|
|
private readonly RenderHandle _renderHandle;
|
|
|
|
public DrawingHandleScreenImpl(RenderHandle renderHandle)
|
|
{
|
|
_renderHandle = renderHandle;
|
|
}
|
|
|
|
public override void SetTransform(in Matrix3 matrix)
|
|
{
|
|
_renderHandle.SetModelTransform(matrix);
|
|
}
|
|
|
|
public override void UseShader(ShaderInstance shader)
|
|
{
|
|
_renderHandle.UseShader(shader);
|
|
}
|
|
|
|
public override void DrawPrimitives(DrawPrimitiveTopology primitiveTopology, ReadOnlySpan<Vector2> vertices,
|
|
Color color)
|
|
{
|
|
var realColor = color * Modulate;
|
|
|
|
_renderHandle.DrawPrimitives(primitiveTopology, vertices, realColor);
|
|
}
|
|
|
|
public override void DrawPrimitives(DrawPrimitiveTopology primitiveTopology, ReadOnlySpan<ushort> indices,
|
|
ReadOnlySpan<Vector2> vertices, Color color)
|
|
{
|
|
var realColor = color * Modulate;
|
|
|
|
_renderHandle.DrawPrimitives(primitiveTopology, indices, vertices, realColor);
|
|
}
|
|
|
|
public override void DrawPrimitives(DrawPrimitiveTopology primitiveTopology, Texture texture,
|
|
ReadOnlySpan<DrawVertexUV2D> vertices, Color? color = null)
|
|
{
|
|
var realColor = (color ?? Color.White) * Modulate;
|
|
|
|
_renderHandle.DrawPrimitives(primitiveTopology, texture, vertices, realColor);
|
|
}
|
|
|
|
public override void DrawPrimitives(DrawPrimitiveTopology primitiveTopology, Texture texture,
|
|
ReadOnlySpan<ushort> indices, ReadOnlySpan<DrawVertexUV2D> vertices, Color? color = null)
|
|
{
|
|
var realColor = (color ?? Color.White) * Modulate;
|
|
|
|
_renderHandle.DrawPrimitives(primitiveTopology, texture, indices, vertices, realColor);
|
|
}
|
|
|
|
public override void DrawLine(Vector2 from, Vector2 to, Color color)
|
|
{
|
|
_renderHandle.DrawLine(@from, to, color * Modulate);
|
|
}
|
|
|
|
public override void DrawRect(UIBox2 rect, Color color, bool filled = true)
|
|
{
|
|
if (filled)
|
|
{
|
|
DrawTextureRect(Texture.White, rect, color);
|
|
}
|
|
else
|
|
{
|
|
DrawLine(rect.TopLeft, rect.TopRight, color);
|
|
DrawLine(rect.TopRight, rect.BottomRight, color);
|
|
DrawLine(rect.BottomRight, rect.BottomLeft, color);
|
|
DrawLine(rect.BottomLeft, rect.TopLeft, color);
|
|
}
|
|
}
|
|
|
|
public override void DrawTextureRectRegion(Texture texture, UIBox2 rect, UIBox2? subRegion = null,
|
|
Color? modulate = null)
|
|
{
|
|
var color = (modulate ?? Color.White) * Modulate;
|
|
_renderHandle.DrawTexture(texture, rect.TopLeft, rect.TopRight,
|
|
rect.BottomLeft, rect.BottomRight, color, subRegion);
|
|
}
|
|
}
|
|
|
|
private sealed class DrawingHandleWorldImpl : DrawingHandleWorld
|
|
{
|
|
private readonly RenderHandle _renderHandle;
|
|
|
|
public DrawingHandleWorldImpl(RenderHandle renderHandle)
|
|
{
|
|
_renderHandle = renderHandle;
|
|
}
|
|
|
|
public override void SetTransform(in Matrix3 matrix)
|
|
{
|
|
_renderHandle.SetModelTransform(matrix);
|
|
}
|
|
|
|
public override void UseShader(ShaderInstance shader)
|
|
{
|
|
_renderHandle.UseShader(shader);
|
|
}
|
|
|
|
public override void DrawCircle(Vector2 position, float radius, Color color, bool filled = true)
|
|
{
|
|
// TODO: Implement this.
|
|
}
|
|
|
|
public override void DrawLine(Vector2 from, Vector2 to, Color color)
|
|
{
|
|
_renderHandle.DrawLine(@from, to, color * Modulate);
|
|
}
|
|
|
|
public override void DrawRect(Box2 rect, Color color, bool filled = true)
|
|
{
|
|
if (filled)
|
|
{
|
|
DrawTextureRect(Texture.White, rect, color);
|
|
}
|
|
else
|
|
{
|
|
DrawLine(rect.TopLeft, rect.TopRight, color);
|
|
DrawLine(rect.TopRight, rect.BottomRight, color);
|
|
DrawLine(rect.BottomRight, rect.BottomLeft, color);
|
|
DrawLine(rect.BottomLeft, rect.TopLeft, color);
|
|
}
|
|
}
|
|
|
|
public override void DrawRect(in Box2Rotated rect, Color color, bool filled = true)
|
|
{
|
|
if (filled)
|
|
{
|
|
DrawTextureRect(Texture.White, rect, color);
|
|
}
|
|
else
|
|
{
|
|
DrawLine(rect.TopLeft, rect.TopRight, color);
|
|
DrawLine(rect.TopRight, rect.BottomRight, color);
|
|
DrawLine(rect.BottomRight, rect.BottomLeft, color);
|
|
DrawLine(rect.BottomLeft, rect.TopLeft, color);
|
|
}
|
|
}
|
|
|
|
public override void DrawTextureRectRegion(Texture texture, Box2 rect, UIBox2? subRegion = null,
|
|
Color? modulate = null)
|
|
{
|
|
var color = (modulate ?? Color.White) * Modulate;
|
|
|
|
_renderHandle.DrawTexture(texture, rect.BottomLeft, rect.BottomRight,
|
|
rect.TopLeft, rect.TopRight, color, subRegion);
|
|
}
|
|
|
|
public override void DrawTextureRectRegion(Texture texture, in Box2Rotated rect,
|
|
UIBox2? subRegion = null, Color? modulate = null)
|
|
{
|
|
var color = (modulate ?? Color.White) * Modulate;
|
|
|
|
_renderHandle.DrawTexture(texture, rect.BottomLeft, rect.BottomRight,
|
|
rect.TopLeft, rect.TopRight, color, subRegion);
|
|
}
|
|
|
|
public override void DrawPrimitives(DrawPrimitiveTopology primitiveTopology, ReadOnlySpan<Vector2> vertices,
|
|
Color color)
|
|
{
|
|
var realColor = color * Modulate;
|
|
|
|
_renderHandle.DrawPrimitives(primitiveTopology, vertices, realColor);
|
|
}
|
|
|
|
public override void DrawPrimitives(DrawPrimitiveTopology primitiveTopology, ReadOnlySpan<ushort> indices,
|
|
ReadOnlySpan<Vector2> vertices, Color color)
|
|
{
|
|
var realColor = color * Modulate;
|
|
|
|
_renderHandle.DrawPrimitives(primitiveTopology, indices, vertices, realColor);
|
|
}
|
|
|
|
public override void DrawPrimitives(DrawPrimitiveTopology primitiveTopology, Texture texture,
|
|
ReadOnlySpan<DrawVertexUV2D> vertices, Color? color = null)
|
|
{
|
|
var realColor = (color ?? Color.White) * Modulate;
|
|
|
|
_renderHandle.DrawPrimitives(primitiveTopology, texture, vertices, realColor);
|
|
}
|
|
|
|
public override void DrawPrimitives(DrawPrimitiveTopology primitiveTopology, Texture texture,
|
|
ReadOnlySpan<ushort> indices, ReadOnlySpan<DrawVertexUV2D> vertices, Color? color = null)
|
|
{
|
|
var realColor = (color ?? Color.White) * Modulate;
|
|
|
|
_renderHandle.DrawPrimitives(primitiveTopology, texture, indices, vertices, realColor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|