Font Rendering #18
			
				
			
		
		
		
	|  | @ -7,3 +7,6 @@ | |||
| [submodule "lib/RefreshCS"] | ||||
| 	path = lib/RefreshCS | ||||
| 	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\RefreshCS\RefreshCS.csproj" /> | ||||
| 		<ProjectReference Include=".\lib\FAudio\csharp\FAudio-CS.Core.csproj" /> | ||||
| 		<ProjectReference Include=".\lib\WellspringCS\WellspringCS.csproj" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
|  |  | |||
|  | @ -11,4 +11,8 @@ | |||
| 	<dllmap dll="FAudio" os="windows" target="FAudio.dll"/> | ||||
| 	<dllmap dll="FAudio" os="osx" target="libFAudio.0.dylib"/> | ||||
| 	<dllmap dll="FAudio" os="linux,freebsd,netbsd" target="libFAudio.so.0"/> | ||||
| 
 | ||||
| 	<dllmap dll="Wellspring" os="windows" target="Wellspring.dll"/> | ||||
| 	<dllmap dll="Wellspring" os="osx" target="libWellspring.0.dylib"/> | ||||
| 	<dllmap dll="Wellspring" os="linux,freebsd,netbsd" target="libWellspring.so.0"/> | ||||
| </configuration> | ||||
|  |  | |||
|  | @ -14,6 +14,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FAudio-CS.Core", "lib\FAudi | |||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RefreshCS", "lib\RefreshCS\RefreshCS.csproj", "{AD7C94E4-0AFA-44CA-889C-110142369893}" | ||||
| 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 | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		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}.Release|x64.ActiveCfg = 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 | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
|  | @ -43,4 +51,7 @@ Global | |||
| 	GlobalSection(ExtensibilityGlobals) = postSolution | ||||
| 		SolutionGuid = {C3D68FAA-3165-43C7-95B3-D845F0DAA918} | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(NestedProjects) = preSolution | ||||
| 		{0DD7B866-773C-4A86-8580-F436DAA28989} = {69D3788D-6C57-44F7-A912-B201AE6D7C04} | ||||
| 	EndGlobalSection | ||||
| EndGlobal | ||||
|  |  | |||
|  | @ -0,0 +1 @@ | |||
| Subproject commit 4b21707900c6d75184f0d5373a0676fe31da956b | ||||
|  | @ -21,6 +21,8 @@ namespace MoonWorks.Graphics | |||
| 			Handle = handle; | ||||
| 		} | ||||
| 
 | ||||
| 		// FIXME: we can probably use the NativeMemory functions to not have to generate arrays here | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// Begins 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 | ||||
| 	{ | ||||
| 		public uint FontSize; | ||||
| 		public uint FirstCodepoint; | ||||
| 		public uint NumChars; | ||||
| 		public byte OversampleH; | ||||
| 		public byte OversampleV; | ||||
| 	} | ||||
| 
 | ||||
| 	[StructLayout(LayoutKind.Sequential)] | ||||
| 	public struct Vertex | ||||
| 	{ | ||||
| 		public Vector3 Position; | ||||
| 		public Vector2 TexCoord; | ||||
| 		public Color Color; | ||||
| 	} | ||||
| } | ||||
|  | @ -0,0 +1,91 @@ | |||
| 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 uint PrimitiveCount { 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; | ||||
| 			PrimitiveCount = 0; | ||||
| 		} | ||||
| 
 | ||||
| 		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!"); | ||||
| 				} | ||||
| 
 | ||||
| 				PrimitiveCount += (uint) (text.Length * 2); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		// 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); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -195,6 +195,7 @@ namespace MoonWorks | |||
| 			NativeLibrary.SetDllImportResolver(typeof(SDL2.SDL).Assembly, MapAndLoad); | ||||
| 			NativeLibrary.SetDllImportResolver(typeof(RefreshCS.Refresh).Assembly, MapAndLoad); | ||||
| 			NativeLibrary.SetDllImportResolver(typeof(FAudio).Assembly, MapAndLoad); | ||||
| 			NativeLibrary.SetDllImportResolver(typeof(WellspringCS.Wellspring).Assembly, MapAndLoad); | ||||
| 		} | ||||
| 
 | ||||
| 		#endregion | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue