add font API
parent
72c9dd4bda
commit
099c1d4fa3
|
@ -7,3 +7,6 @@
|
||||||
[submodule "lib/RefreshCS"]
|
[submodule "lib/RefreshCS"]
|
||||||
path = lib/RefreshCS
|
path = lib/RefreshCS
|
||||||
url = https://gitea.moonside.games/MoonsideGames/RefreshCS.git
|
url = https://gitea.moonside.games/MoonsideGames/RefreshCS.git
|
||||||
|
[submodule "lib/WellspringCS"]
|
||||||
|
path = lib/WellspringCS
|
||||||
|
url = https://gitea.moonside.games/MoonsideGames/WellspringCS.git
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
<ProjectReference Include=".\lib\SDL2-CS\SDL2-CS.Core.csproj" />
|
<ProjectReference Include=".\lib\SDL2-CS\SDL2-CS.Core.csproj" />
|
||||||
<ProjectReference Include=".\lib\RefreshCS\RefreshCS.csproj" />
|
<ProjectReference Include=".\lib\RefreshCS\RefreshCS.csproj" />
|
||||||
<ProjectReference Include=".\lib\FAudio\csharp\FAudio-CS.Core.csproj" />
|
<ProjectReference Include=".\lib\FAudio\csharp\FAudio-CS.Core.csproj" />
|
||||||
|
<ProjectReference Include="lib\WellspringCS\WellspringCS.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -14,6 +14,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FAudio-CS.Core", "lib\FAudi
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RefreshCS", "lib\RefreshCS\RefreshCS.csproj", "{AD7C94E4-0AFA-44CA-889C-110142369893}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RefreshCS", "lib\RefreshCS\RefreshCS.csproj", "{AD7C94E4-0AFA-44CA-889C-110142369893}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{69D3788D-6C57-44F7-A912-B201AE6D7C04}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WellspringCS", "lib\WellspringCS\WellspringCS.csproj", "{0DD7B866-773C-4A86-8580-F436DAA28989}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
|
@ -36,6 +40,10 @@ Global
|
||||||
{AD7C94E4-0AFA-44CA-889C-110142369893}.Debug|x64.Build.0 = Debug|x64
|
{AD7C94E4-0AFA-44CA-889C-110142369893}.Debug|x64.Build.0 = Debug|x64
|
||||||
{AD7C94E4-0AFA-44CA-889C-110142369893}.Release|x64.ActiveCfg = Release|x64
|
{AD7C94E4-0AFA-44CA-889C-110142369893}.Release|x64.ActiveCfg = Release|x64
|
||||||
{AD7C94E4-0AFA-44CA-889C-110142369893}.Release|x64.Build.0 = Release|x64
|
{AD7C94E4-0AFA-44CA-889C-110142369893}.Release|x64.Build.0 = Release|x64
|
||||||
|
{0DD7B866-773C-4A86-8580-F436DAA28989}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{0DD7B866-773C-4A86-8580-F436DAA28989}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{0DD7B866-773C-4A86-8580-F436DAA28989}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{0DD7B866-773C-4A86-8580-F436DAA28989}.Release|x64.Build.0 = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -43,4 +51,7 @@ Global
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {C3D68FAA-3165-43C7-95B3-D845F0DAA918}
|
SolutionGuid = {C3D68FAA-3165-43C7-95B3-D845F0DAA918}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{0DD7B866-773C-4A86-8580-F436DAA28989} = {69D3788D-6C57-44F7-A912-B201AE6D7C04}
|
||||||
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 4b21707900c6d75184f0d5373a0676fe31da956b
|
|
@ -21,6 +21,8 @@ namespace MoonWorks.Graphics
|
||||||
Handle = handle;
|
Handle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: we can probably use the NativeMemory functions to not have to generate arrays here
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Begins a render pass.
|
/// Begins a render pass.
|
||||||
/// All render state, resource binding, and draw commands must be made within a render pass.
|
/// All render state, resource binding, and draw commands must be made within a render pass.
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using WellspringCS;
|
||||||
|
|
||||||
|
namespace MoonWorks.Graphics.Font
|
||||||
|
{
|
||||||
|
public class Packer : IDisposable
|
||||||
|
{
|
||||||
|
public IntPtr Handle { get; }
|
||||||
|
public Texture Texture { get; }
|
||||||
|
|
||||||
|
private bool IsDisposed;
|
||||||
|
|
||||||
|
public unsafe Packer(GraphicsDevice graphicsDevice, string path, uint textureWidth, uint textureHeight, uint padding = 1)
|
||||||
|
{
|
||||||
|
var bytes = File.ReadAllBytes(path);
|
||||||
|
fixed (byte* pByte = &bytes[0])
|
||||||
|
{
|
||||||
|
Handle = Wellspring.Wellspring_CreatePacker((IntPtr) pByte, (uint) bytes.Length, textureWidth, textureHeight, 0, padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture = Texture.CreateTexture2D(graphicsDevice, textureWidth, textureHeight, TextureFormat.R8, TextureUsageFlags.Sampler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe bool PackFontRanges(params FontRange[] fontRanges)
|
||||||
|
{
|
||||||
|
fixed (FontRange *pFontRanges = &fontRanges[0])
|
||||||
|
{
|
||||||
|
var nativeSize = fontRanges.Length * Marshal.SizeOf<Wellspring.FontRange>();
|
||||||
|
void* fontRangeMemory = NativeMemory.Alloc((nuint) fontRanges.Length, (nuint) Marshal.SizeOf<Wellspring.FontRange>());
|
||||||
|
System.Buffer.MemoryCopy(pFontRanges, fontRangeMemory, nativeSize, nativeSize);
|
||||||
|
|
||||||
|
var result = Wellspring.Wellspring_PackFontRanges(Handle, (IntPtr) fontRangeMemory, (uint) fontRanges.Length);
|
||||||
|
|
||||||
|
NativeMemory.Free(fontRangeMemory);
|
||||||
|
|
||||||
|
return result > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void SetTextureData(CommandBuffer commandBuffer)
|
||||||
|
{
|
||||||
|
var pixelDataPointer = Wellspring.Wellspring_GetPixelDataPointer(Handle);
|
||||||
|
commandBuffer.SetTextureData(Texture, pixelDataPointer, Texture.Width * Texture.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!IsDisposed)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
Texture.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Wellspring.Wellspring_DestroyPacker(Handle);
|
||||||
|
|
||||||
|
IsDisposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~Packer()
|
||||||
|
{
|
||||||
|
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
||||||
|
Dispose(disposing: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
||||||
|
Dispose(disposing: true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using MoonWorks.Math;
|
||||||
|
|
||||||
|
namespace MoonWorks.Graphics.Font
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct FontRange
|
||||||
|
{
|
||||||
|
uint FontSize;
|
||||||
|
uint FirstCodepoint;
|
||||||
|
uint NumChars;
|
||||||
|
byte OversampleH;
|
||||||
|
byte OversampleV;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct Vertex
|
||||||
|
{
|
||||||
|
public Vector3 Position;
|
||||||
|
public Vector2 TexCoord;
|
||||||
|
public Color Color;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
using System;
|
||||||
|
using WellspringCS;
|
||||||
|
|
||||||
|
namespace MoonWorks.Graphics.Font
|
||||||
|
{
|
||||||
|
public class TextBatch
|
||||||
|
{
|
||||||
|
private GraphicsDevice GraphicsDevice { get; }
|
||||||
|
public IntPtr Handle { get; }
|
||||||
|
|
||||||
|
public Buffer VertexBuffer { get; protected set; } = null;
|
||||||
|
public Buffer IndexBuffer { get; protected set; } = null;
|
||||||
|
public Texture Texture { get; protected set; }
|
||||||
|
|
||||||
|
public TextBatch(GraphicsDevice graphicsDevice)
|
||||||
|
{
|
||||||
|
GraphicsDevice = graphicsDevice;
|
||||||
|
Handle = Wellspring.Wellspring_CreateTextBatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start(Packer packer)
|
||||||
|
{
|
||||||
|
Wellspring.Wellspring_StartTextBatch(Handle, packer.Handle);
|
||||||
|
Texture = packer.Texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void Draw(float x, float y, float depth, Color color, string text)
|
||||||
|
{
|
||||||
|
fixed (char* chars = text)
|
||||||
|
{
|
||||||
|
var byteCount = System.Text.Encoding.UTF8.GetByteCount(text);
|
||||||
|
var bytes = stackalloc byte[byteCount];
|
||||||
|
System.Text.Encoding.UTF8.GetBytes(chars, text.Length, bytes, byteCount);
|
||||||
|
|
||||||
|
var result = Wellspring.Wellspring_Draw(
|
||||||
|
Handle,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
depth,
|
||||||
|
new Wellspring.Color { R = color.R, G = color.G, B = color.B, A = color.A },
|
||||||
|
(IntPtr) bytes,
|
||||||
|
(uint) byteCount
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == 0)
|
||||||
|
{
|
||||||
|
throw new System.ArgumentException("Could not decode string!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call this after you have made all the Draw calls you want.
|
||||||
|
public unsafe void UploadBufferData(CommandBuffer commandBuffer)
|
||||||
|
{
|
||||||
|
Wellspring.Wellspring_GetBufferData(
|
||||||
|
Handle,
|
||||||
|
out IntPtr vertexDataPointer,
|
||||||
|
out uint vertexDataLengthInBytes,
|
||||||
|
out IntPtr indexDataPointer,
|
||||||
|
out uint indexDataLengthInBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
if (VertexBuffer == null)
|
||||||
|
{
|
||||||
|
VertexBuffer = new Buffer(GraphicsDevice, BufferUsageFlags.Vertex, vertexDataLengthInBytes);
|
||||||
|
}
|
||||||
|
else if (VertexBuffer.Size < vertexDataLengthInBytes)
|
||||||
|
{
|
||||||
|
VertexBuffer.Dispose();
|
||||||
|
VertexBuffer = new Buffer(GraphicsDevice, BufferUsageFlags.Vertex, vertexDataLengthInBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IndexBuffer == null)
|
||||||
|
{
|
||||||
|
IndexBuffer = new Buffer(GraphicsDevice, BufferUsageFlags.Index, indexDataLengthInBytes);
|
||||||
|
}
|
||||||
|
else if (IndexBuffer.Size < indexDataLengthInBytes)
|
||||||
|
{
|
||||||
|
IndexBuffer.Dispose();
|
||||||
|
IndexBuffer = new Buffer(GraphicsDevice, BufferUsageFlags.Index, indexDataLengthInBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
commandBuffer.SetBufferData(VertexBuffer, vertexDataPointer, 0, vertexDataLengthInBytes);
|
||||||
|
commandBuffer.SetBufferData(IndexBuffer, indexDataPointer, 0, indexDataLengthInBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue