diff --git a/.vscode/launch.json b/.vscode/launch.json index 16ef71c..d917045 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,16 +5,16 @@ "version": "0.2.0", "configurations": [ { - "name": ".NET Core Launch (console)", + "name": "SlatedGameToolkit.Tools", "type": "coreclr", "request": "launch", "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. - "program": "${workspaceFolder}/src/SlatedGameToolkit.Tools/bin/Debug/netcoreapp3.1/SlatedGameToolkit.Tools.dll", + "program": "${workspaceFolder}/src/SlatedGameToolkit.Tools/bin/Debug/netcoreapp3.1/SlatedGameToolkit.Tools.exe", "args": [], "cwd": "${workspaceFolder}/src/SlatedGameToolkit.Tools", // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console - "console": "internalConsole", + "console": "integratedTerminal", "stopAtEntry": false }, { diff --git a/src/SlatedGameToolkit.Framework/Exceptions/OpenGLErrorException.cs b/src/SlatedGameToolkit.Framework/Exceptions/OpenGLErrorException.cs index 110fdbd..ddef5d6 100644 --- a/src/SlatedGameToolkit.Framework/Exceptions/OpenGLErrorException.cs +++ b/src/SlatedGameToolkit.Framework/Exceptions/OpenGLErrorException.cs @@ -21,8 +21,8 @@ namespace SlatedGameToolkit.Framework.Exceptions /// public static void CheckGLErrorStatus() { uint errorCode = WindowContextsManager.CurrentWindowContext.GetGLStatus(); - if (errorCode != (uint) GLEnums.GL_NO_ERROR) { - throw new OpenGLErrorException(errorCode, "OpenGL error: " + errorCode.ToString()); + if (errorCode != (uint) GLEnum.GL_NO_ERROR) { + throw new OpenGLErrorException(errorCode, string.Format("OpenGL error ({0}): {1}", errorCode, ((GLEnum) errorCode))); } } } diff --git a/src/SlatedGameToolkit.Framework/GameEngine.cs b/src/SlatedGameToolkit.Framework/GameEngine.cs index a7685c1..b408eeb 100644 --- a/src/SlatedGameToolkit.Framework/GameEngine.cs +++ b/src/SlatedGameToolkit.Framework/GameEngine.cs @@ -4,6 +4,7 @@ using SDL2; using Serilog; using Serilog.Core; using SlatedGameToolkit.Framework.Exceptions; +using SlatedGameToolkit.Framework.Graphics; using SlatedGameToolkit.Framework.Graphics.Window; using SlatedGameToolkit.Framework.Input; using SlatedGameToolkit.Framework.Input.Devices; @@ -76,9 +77,10 @@ namespace SlatedGameToolkit.Framework { private static void Loop(Object o) { if (!(o is IState)) throw new InternalFrameworkException(String.Format("Expected initial state object for asynchronous loop. Got {0}", o)); - IState initialState = (IState) o; - Manager manager = new Manager(initialState); + StateManager manager = new StateManager(); try { + IState initialState = (IState) o; + manager.Initialize(initialState); DateTime currentTime = DateTime.Now; TimeSpan timePassedFromLastUpdate = TimeSpan.Zero; TimeSpan timePassedFromLastRender = TimeSpan.Zero; @@ -170,6 +172,8 @@ namespace SlatedGameToolkit.Framework { timePassedFromLastRender = TimeSpan.Zero; } } + } catch (Exception e) { + Logger.Fatal(e.ToString()); } finally { stopped = true; manager.Dispose(); @@ -228,8 +232,8 @@ namespace SlatedGameToolkit.Framework { throw new FrameworkSDLException(); } - if (SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_MAJOR_VERSION, 3) < 0) throw new FrameworkSDLException(); - if (SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_MINOR_VERSION, 1) < 0) throw new FrameworkSDLException(); + if (SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_MAJOR_VERSION, OpenGL.OpenGLMajorVersion) < 0) throw new FrameworkSDLException(); + if (SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_MINOR_VERSION, OpenGL.OpenGLMinorVersion) < 0) throw new FrameworkSDLException(); if (SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_PROFILE_MASK, SDL.SDL_GLprofile.SDL_GL_CONTEXT_PROFILE_CORE) < 0) throw new FrameworkSDLException(); thread = new Thread(Loop); diff --git a/src/SlatedGameToolkit.Framework/Graphics/GLEnums.cs b/src/SlatedGameToolkit.Framework/Graphics/GLEnum.cs similarity index 99% rename from src/SlatedGameToolkit.Framework/Graphics/GLEnums.cs rename to src/SlatedGameToolkit.Framework/Graphics/GLEnum.cs index 3dfc1ae..e795ad5 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/GLEnums.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/GLEnum.cs @@ -1,6 +1,6 @@ namespace SlatedGameToolkit.Framework.Graphics { - public enum GLEnums: uint { + public enum GLEnum: uint { GL_DEPTH_BUFFER_BIT = 0x00000100, GL_STENCIL_BUFFER_BIT = 0x00000400, GL_COLOR_BUFFER_BIT = 0x00004000, diff --git a/src/SlatedGameToolkit.Framework/Graphics/Meshes/RectangleMesh.cs b/src/SlatedGameToolkit.Framework/Graphics/Meshes/RectangleMesh.cs index da337c7..831d871 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Meshes/RectangleMesh.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Meshes/RectangleMesh.cs @@ -6,9 +6,9 @@ namespace SlatedGameToolkit.Framework.Graphics.Meshes { public abstract class RectangleMesh : IMeshable { - private bool changed = true; - private Matrix4x4 matRot, matTrans, matScale; - private Vector3 rotation, translation, scale; + private Matrix4x4 matRot; + private bool changed; + private Vector3 rotation; private Vector2 origin, dimensions; protected readonly Vector2[] textureCoords = new Vector2[4]; private ValueTuple[] vertices = new ValueTuple[4]; @@ -78,35 +78,6 @@ namespace SlatedGameToolkit.Framework.Graphics.Meshes public uint[] Elements { get {return indices; } } - public Vector3 Translation - { - get - { - return rotation; - } - set - { - changed = true; - translation = value; - matTrans = Matrix4x4.CreateTranslation(value); - } - } - - public Vector3 Scale - { - get - { - return scale; - } - - set - { - changed = true; - scale = value; - matScale = Matrix4x4.CreateScale(value); - } - } - public Vector3 Rotation { get @@ -122,16 +93,16 @@ namespace SlatedGameToolkit.Framework.Graphics.Meshes } } private void CalculateVertices() { + if (!changed) return; Vector3[] baseVerts = new Vector3[4]; baseVerts[0] = new Vector3(this.origin, 0); baseVerts[1] = new Vector3(this.origin.X + this.dimensions.X, this.origin.Y, 0); baseVerts[2] = new Vector3(baseVerts[1].X, this.origin.Y + this.dimensions.Y, 0); baseVerts[3] = new Vector3(this.origin.X, baseVerts[2].Y, 0); - Matrix4x4 transform = matTrans * matRot * matScale; for (int i = 0; i < vertices.Length; i++) { - vertices[i] = new ValueTuple(Vector3.Transform(baseVerts[i], transform), textureCoords[i]); + vertices[i] = new ValueTuple(Vector3.Transform(baseVerts[i], matRot), textureCoords[i]); } changed = false; } diff --git a/src/SlatedGameToolkit.Framework/Graphics/GLFunctionDelegates.cs b/src/SlatedGameToolkit.Framework/Graphics/OpenGL.cs similarity index 72% rename from src/SlatedGameToolkit.Framework/Graphics/GLFunctionDelegates.cs rename to src/SlatedGameToolkit.Framework/Graphics/OpenGL.cs index e65556c..ba98028 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/GLFunctionDelegates.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/OpenGL.cs @@ -2,23 +2,25 @@ using System; using System.Runtime.InteropServices; using SDL2; using SlatedGameToolkit.Framework.Exceptions; +using SlatedGameToolkit.Framework.Graphics.Programs; +using SlatedGameToolkit.Framework.Graphics.Shaders; namespace SlatedGameToolkit.Framework.Graphics { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GLClearColour(float r, float g, float b); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLClear(GLEnums flags); + public delegate void GLClear(GLEnum flags); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GLViewport(int x, int y, int width, int height); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate UIntPtr GLCreateShader(GLEnums type); + public delegate UIntPtr GLCreateShader(GLEnum type); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate UIntPtr GLShaderSource(UIntPtr shaderHandle, uint count, string program, int[] length); + public delegate UIntPtr GLShaderSource(UIntPtr shaderHandle, uint count, string[] program, int[] length); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GLCompileShader(UIntPtr shaderHandle); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLGetShaderLogInfo(UIntPtr shader, uint maxLength, out uint writtenLength, out string output); + public delegate void GLGetShaderInfoLog(UIntPtr shader, uint maxLength, out uint writtenLength, byte[] output); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate UIntPtr GLCreateProgram(); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -32,11 +34,11 @@ namespace SlatedGameToolkit.Framework.Graphics [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GLBindAttribLocation(UIntPtr program, uint index, string name); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLGetProgramInfoLog(UIntPtr program, uint maxLength, out uint writtenLength, out string output); + public delegate void GLGetProgramInfoLog(UIntPtr program, uint maxLength, out uint writtenLength, byte[] output); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GLLinkProgram(UIntPtr program); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLProgramParameter(UIntPtr program, GLEnums parameterName, int value); + public delegate void GLProgramParameter(UIntPtr program, GLEnum parameterName, int value); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GLUseProgram(UIntPtr program); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -46,21 +48,21 @@ namespace SlatedGameToolkit.Framework.Graphics [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GLBindProgramPipeline(UIntPtr pipeline); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLUseProgramStages(UIntPtr pipeline, GLEnums bitField, UIntPtr program); + public delegate void GLUseProgramStages(UIntPtr pipeline, GLEnum bitField, UIntPtr program); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate uint GLGetError(); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int GLGetAttribLocation(UIntPtr program, string attribName); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLBindBuffer(GLEnums target, UIntPtr buffer); + public delegate void GLBindBuffer(GLEnum target, UIntPtr buffer); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GLGenBuffers(uint size, UIntPtr[] buffers); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public unsafe delegate void GLBufferData(GLEnums target, uint size, Array data, GLEnums usage); + public unsafe delegate void GLBufferData(GLEnum target, uint size, Array data, GLEnum usage); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GLDeleteBuffers(uint size, UIntPtr[] buffers); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLVertexAttribPointer(uint index, int size, GLEnums type, bool normalized, uint stride, uint offset); + public delegate void GLVertexAttribPointer(uint index, int size, GLEnum type, bool normalized, uint stride, uint offset); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GLGenVertexArrays(uint amount, UIntPtr[] arrays); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -72,33 +74,39 @@ namespace SlatedGameToolkit.Framework.Graphics [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GLDisableVertexAttribArray(uint attribIndex); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLDrawArrays(GLEnums mode, int first, uint count); + public delegate void GLDrawArrays(GLEnum mode, int first, uint count); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLDrawElements(GLEnums mode, uint count, int offset); + public delegate void GLDrawElements(GLEnum mode, uint count, int offset); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLMultiDrawArrays(GLEnums mode, int[] first, uint[] count, uint primout); + public delegate void GLMultiDrawArrays(GLEnum mode, int[] first, uint[] count, uint primout); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLMultiDrawElements(GLEnums mode, uint[] count, GLEnums type, IntPtr indices, int length); + public delegate void GLMultiDrawElements(GLEnum mode, uint[] count, GLEnum type, uint[] indiceOffsets, int length); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GLGenTextures(uint n, UIntPtr[] textureHandles); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLBindTexture(GLEnums target, UIntPtr texture); + public delegate void GLBindTexture(GLEnum target, UIntPtr texture); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GLDeleteTextures(uint n, UIntPtr[] textureHandles); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLTexParameteri(GLEnums target, GLEnums pname, int value); + public delegate void GLTexParameteri(GLEnum target, GLEnum pname, int value); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLTexParameterf(GLEnums target, GLEnums pname, float value); + public delegate void GLTexParameterf(GLEnum target, GLEnum pname, float value); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLTexParameteriv(GLEnums target, GLEnums pname, int[] values); + public delegate void GLTexParameteriv(GLEnum target, GLEnum pname, int[] values); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLTexParameterfv(GLEnums target, GLEnums pname, float[] values); + public delegate void GLTexParameterfv(GLEnum target, GLEnum pname, float[] values); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLTexImage2D(GLEnums target, int level, int publicFormat, uint width, uint height, int border, GLEnums format, GLEnums type, byte[] data); + public delegate void GLTexImage2D(GLEnum target, int level, int publicFormat, uint width, uint height, int border, GLEnum format, GLEnum type, byte[] data); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void GLGenerateMipMap(GLEnums target); + public delegate void GLGenerateMipmap(GLEnum target); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int GLGetUniformLocation(UIntPtr program, string name); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void GLUniformMatrix4fv(int index, uint count, bool transpose, float[] matrix); - public static class GLFunctionUtils { + public static class OpenGL { + public const int OpenGLMajorVersion = 3; + public const int OpenGLMinorVersion = 3; /// /// Attempts to retrieve and instantiate an OpenGL function as a C# delegate. /// Make sure the delegates signature is correct as failing to do so will potentially @@ -112,7 +120,7 @@ namespace SlatedGameToolkit.Framework.Graphics public static T RetrieveGLDelegate(string functionName) where T : Delegate { GameEngine.Logger.Debug(String.Format("Retrieving function with name: {0}", functionName)); IntPtr functionAddress = SDL.SDL_GL_GetProcAddress(functionName); - if (functionAddress == null) throw new FrameworkSDLException(); + if (functionAddress.Equals(IntPtr.Zero)) throw new FrameworkSDLException(); return Marshal.GetDelegateForFunctionPointer(functionAddress); } } diff --git a/src/SlatedGameToolkit.Framework/Graphics/Programs/GLProgram.cs b/src/SlatedGameToolkit.Framework/Graphics/Programs/GLProgram.cs index dd9b316..3413fd8 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Programs/GLProgram.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Programs/GLProgram.cs @@ -1,7 +1,10 @@ using System; +using System.Numerics; using System.Runtime.InteropServices; +using System.Text; using SDL2; using SlatedGameToolkit.Framework.Exceptions; +using SlatedGameToolkit.Framework.Graphics; using SlatedGameToolkit.Framework.Graphics.Window; namespace SlatedGameToolkit.Framework.Graphics.Programs @@ -21,6 +24,10 @@ namespace SlatedGameToolkit.Framework.Graphics.Programs protected GLGetProgramInfoLog getProgramInfoLog; protected GLProgramParameter programParameter; private GLUseProgram useProgram; + private readonly GLGetAttribLocation getAttribLocation; + private readonly GLGetUniformLocation getUniformLocation; + private readonly GLUniformMatrix4fv uniformMatrix4Fv; + /// /// Creates an OpenGL program. @@ -29,14 +36,43 @@ namespace SlatedGameToolkit.Framework.Graphics.Programs /// internal GLProgram() { this.context = WindowContextsManager.CurrentWindowContext; - createProgram = GLFunctionUtils.RetrieveGLDelegate("glCreateProgram"); - deleteProgram = GLFunctionUtils.RetrieveGLDelegate("glDeleteProgram"); - linkProgram = GLFunctionUtils.RetrieveGLDelegate("glLinkProgram"); - getProgramInfoLog = GLFunctionUtils.RetrieveGLDelegate("glGetProgramInfoLog"); - programParameter = GLFunctionUtils.RetrieveGLDelegate("glProgramParameteri"); - useProgram = GLFunctionUtils.RetrieveGLDelegate("glUseProgram"); + createProgram = OpenGL.RetrieveGLDelegate("glCreateProgram"); + deleteProgram = OpenGL.RetrieveGLDelegate("glDeleteProgram"); + linkProgram = OpenGL.RetrieveGLDelegate("glLinkProgram"); + getProgramInfoLog = OpenGL.RetrieveGLDelegate("glGetProgramInfoLog"); + programParameter = OpenGL.RetrieveGLDelegate("glProgramParameteri"); + useProgram = OpenGL.RetrieveGLDelegate("glUseProgram"); + getAttribLocation = OpenGL.RetrieveGLDelegate("glGetAttribLocation"); + getUniformLocation = OpenGL.RetrieveGLDelegate("glGetUniformLocation"); + uniformMatrix4Fv = OpenGL.RetrieveGLDelegate("glUniformMatrix4fv"); handle = createProgram(); + OpenGLErrorException.CheckGLErrorStatus(); + } + + + public int GetAttributeLocation(string name) { + int res = getAttribLocation(handle, name); + OpenGLErrorException.CheckGLErrorStatus(); + return res; + } + + public int GetUniformLocation(string name) { + int res = getUniformLocation(handle, name); + OpenGLErrorException.CheckGLErrorStatus(); + return res; + } + + public void SetUniformMatrix4x4(int location, Matrix4x4 matrix, bool transpose = false) { + Use(); + float[] mat4 = new float[] { + matrix.M11, matrix.M21, matrix.M31, matrix.M41, + matrix.M21, matrix.M22, matrix.M23, matrix.M24, + matrix.M31, matrix.M32, matrix.M33, matrix.M34, + matrix.M41, matrix.M42, matrix.M43, matrix.M44 + }; + uniformMatrix4Fv(location, 1, transpose, mat4); + OpenGLErrorException.CheckGLErrorStatus(); } /// @@ -44,6 +80,13 @@ namespace SlatedGameToolkit.Framework.Graphics.Programs /// public virtual void Use() { useProgram(handle); + uint written; + byte[] log = new byte[2048]; + getProgramInfoLog(handle, (uint)log.Length, out written, log); + if (written > 0) { + throw new OpenGLException(Encoding.UTF8.GetString(log)); + } + OpenGLErrorException.CheckGLErrorStatus(); } /// diff --git a/src/SlatedGameToolkit.Framework/Graphics/Programs/GLShaderProgram.cs b/src/SlatedGameToolkit.Framework/Graphics/Programs/GLShaderProgram.cs index 62e58ac..9a46d16 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Programs/GLShaderProgram.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Programs/GLShaderProgram.cs @@ -1,5 +1,7 @@ using System; +using System.Text; using SlatedGameToolkit.Framework.Exceptions; +using SlatedGameToolkit.Framework.Graphics; using SlatedGameToolkit.Framework.Graphics.Shaders; namespace SlatedGameToolkit.Framework.Graphics.Programs @@ -9,37 +11,38 @@ namespace SlatedGameToolkit.Framework.Graphics.Programs private readonly GLShader[] shaders; private readonly GLAttachShader attachShader; private readonly GLDetachShader detachShader; - private GLBindAttribLocation bindAttribLocation; - public GLShaderProgram(bool separable = true, params GLShader[] shaders) : base() { + public GLShaderProgram(params GLShader[] shaders) : base() { if (shaders.Length == 0) throw new ArgumentException("Requires at least one shader for shader program."); this.shaders = shaders; + + attachShader = OpenGL.RetrieveGLDelegate("glAttachShader"); + detachShader = OpenGL.RetrieveGLDelegate("glDetachShader"); + - attachShader = GLFunctionUtils.RetrieveGLDelegate("glAttachShader"); - bindAttribLocation = GLFunctionUtils.RetrieveGLDelegate("glBindAttribLocation"); - detachShader = GLFunctionUtils.RetrieveGLDelegate("glDetachShader"); - - Use(); - foreach (GLShader shader in shaders) { attachShader(handle, shader.Handle); + OpenGLErrorException.CheckGLErrorStatus(); } linkProgram(handle); uint length; - string log; - getProgramInfoLog(handle, 1024, out length, out log); + byte[] log = new byte[2048]; + getProgramInfoLog(handle, (uint)log.Length, out length, log); if (length > 0) { Dispose(); - throw new OpenGLException(log); + throw new OpenGLException(Encoding.UTF8.GetString(log)); } + OpenGLErrorException.CheckGLErrorStatus(); foreach (GLShader shader in shaders) { detachShader(handle, shader.Handle); + OpenGLErrorException.CheckGLErrorStatus(); } } + /// /// Disposes of the shaders and this program. /// diff --git a/src/SlatedGameToolkit.Framework/Graphics/Render/Batch.cs b/src/SlatedGameToolkit.Framework/Graphics/Render/Batch.cs index 62b64bf..0e63711 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Render/Batch.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Render/Batch.cs @@ -5,47 +5,60 @@ using SlatedGameToolkit.Framework.Graphics.Meshes; using SlatedGameToolkit.Framework.Graphics; using SlatedGameToolkit.Framework.Graphics.Textures; using SlatedGameToolkit.Framework.Graphics.Shaders; +using SlatedGameToolkit.Framework.Graphics.Programs; +using SlatedGameToolkit.Framework.Exceptions; namespace SlatedGameToolkit.Framework.Graphics.Render { public class Batch : IDisposable { + private int projLoc, viewLoc, modelLoc; + private Camera camera; + private GLShaderProgram shaderProgram; private Texture texture; private bool disposed; private VertexArray vertexArray; - private const int VERTEX_LENGTH = 6; + private const int VERTEX_LENGTH = 9; private GLMultiDrawElements multiDrawElements; public bool Batching { get; private set; } + + private Matrix4x4 modelsMatrix; private float[] data; private uint[] indices; private uint[] lengths; private uint[] offsets; private uint dataIndex, indicesIndex, lengthsIndex; - public Batch(uint BatchVertexSize = 4096) { - multiDrawElements = GLFunctionUtils.RetrieveGLDelegate("glMultiDrawElements"); + public Batch(Camera camera, GLShaderProgram shaderProgram, uint BatchVertexSize = 4096) { + multiDrawElements = OpenGL.RetrieveGLDelegate("glMultiDrawElements"); + this.camera = camera; + this.shaderProgram = shaderProgram; indices = new uint[BatchVertexSize]; lengths = new uint[BatchVertexSize]; offsets = new uint[BatchVertexSize]; data = new float[BatchVertexSize * VERTEX_LENGTH]; - vertexArray = new VertexArray(); - + GLGetAttribLocation attribLocation = OpenGL.RetrieveGLDelegate("glGetAttribLocation"); VertexAttributeDefinition[] definitions = new VertexAttributeDefinition[3]; - definitions[0] = new VertexAttributeDefinition(0, 3, 3 * sizeof(float), 0); - definitions[1] = new VertexAttributeDefinition(1, 4, 1 * sizeof(float), 3 * sizeof(float)); - definitions[2] = new VertexAttributeDefinition(2, 2, 2 * sizeof(float), 4 * sizeof(float)); + definitions[0] = new VertexAttributeDefinition((uint)shaderProgram.GetAttributeLocation("aPosition"), 3, 3 * sizeof(float), 0); + definitions[1] = new VertexAttributeDefinition((uint)shaderProgram.GetAttributeLocation("aColor"), 4, 4 * sizeof(float), 3 * sizeof(float)); + definitions[2] = new VertexAttributeDefinition((uint)shaderProgram.GetAttributeLocation("aTexCoord"), 2, 2 * sizeof(float), (4 + 3) * sizeof(float)); + modelLoc = shaderProgram.GetUniformLocation("models"); + viewLoc = shaderProgram.GetUniformLocation("view"); + projLoc = shaderProgram.GetUniformLocation("projection"); vertexArray.defineVertexAttributes(definitions: definitions); } - public virtual void Begin(Texture texture) { + public virtual void Begin(Texture texture, Matrix4x4 modelsMatrix) { if (Batching) throw new InvalidOperationException("This batch is already started."); this.texture = texture ?? throw new ArgumentNullException("texture"); this.Batching = true; + this.modelsMatrix = modelsMatrix; } public virtual void Dispose() { if (disposed) return; + if (Batching) End(); disposed = true; vertexArray.Dispose(); } @@ -62,7 +75,13 @@ namespace SlatedGameToolkit.Framework.Graphics.Render data[dataIndex] = vertices[i].Item1.Z; dataIndex++; - data[dataIndex] = color.ToArgb(); + data[dataIndex] = (float) color.A / byte.MaxValue; + dataIndex++; + data[dataIndex] = (float) color.R / byte.MaxValue; + dataIndex++; + data[dataIndex] = (float) color.G / byte.MaxValue; + dataIndex++; + data[dataIndex] = (float) color.B / byte.MaxValue; dataIndex++; data[dataIndex] = vertices[i].Item2.X; @@ -93,7 +112,10 @@ namespace SlatedGameToolkit.Framework.Graphics.Render dataIndex = 0; indicesIndex = 0; lengthsIndex = 0; - multiDrawElements(GLEnums.GL_TRIANGLE_STRIP, lengths, GLEnums.GL_UNSIGNED_INT, IntPtr.Zero, lengths.Length); + shaderProgram.SetUniformMatrix4x4(modelLoc, modelsMatrix); + shaderProgram.SetUniformMatrix4x4(viewLoc, camera.ViewMatrix); + shaderProgram.SetUniformMatrix4x4(projLoc, camera.ProjectionMatrix); + multiDrawElements(GLEnum.GL_TRIANGLE_STRIP, lengths, GLEnum.GL_UNSIGNED_INT, offsets, lengths.Length); } } } \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Graphics/Render/Camera.cs b/src/SlatedGameToolkit.Framework/Graphics/Render/Camera.cs new file mode 100644 index 0000000..74bc458 --- /dev/null +++ b/src/SlatedGameToolkit.Framework/Graphics/Render/Camera.cs @@ -0,0 +1,103 @@ +using System.Numerics; + +namespace SlatedGameToolkit.Framework.Graphics.Render +{ + public class Camera { + private bool viewUpdated, projectionUpdated; + public virtual Vector3 Up { get; set; } + private Vector3 trans, lookAt; + private float nearField, farField; + private float width, height; + private Matrix4x4 lookAtMatrix; + private Matrix4x4 view, projection; + public virtual bool Orthographic { get; set; } + + public virtual Vector3 Position { + get { + return trans; + } + + set { + this.trans = value; + viewUpdated = true; + } + } + + public Vector3 LookAt { + get { + return lookAt; + } + + set { + this.lookAt = value; + lookAtMatrix = Matrix4x4.CreateLookAt(-trans, value, Up); + viewUpdated = true; + } + } + + public virtual float NearField { + get { + return nearField; + } + + set { + nearField = value; + projectionUpdated = true; + } + } + + public virtual float FarField { + get { + return farField; + } + + set { + farField = value; + projectionUpdated = true; + } + } + + public virtual float Width { + get { + return width; + } + set { + width = value; + projectionUpdated = true; + } + } + public virtual float Height { + get { + return height; + } + set { + height = value; + projectionUpdated = true; + } + } + + public Matrix4x4 ViewMatrix { + get { + if (viewUpdated) { + view = Matrix4x4.CreateTranslation(-trans) * lookAtMatrix; + viewUpdated = false; + } + return view; + } + } + + public Matrix4x4 ProjectionMatrix { + get { + if (projectionUpdated) { + if (Orthographic) { + projection = Matrix4x4.CreateOrthographic(width, height, nearField, farField); + } else { + projection = Matrix4x4.CreatePerspective(width, height, nearField, farField); + } + projectionUpdated = false; + } + return projection; + } + } + } +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Graphics/Render/Camera2D.cs b/src/SlatedGameToolkit.Framework/Graphics/Render/Camera2D.cs new file mode 100644 index 0000000..a54058d --- /dev/null +++ b/src/SlatedGameToolkit.Framework/Graphics/Render/Camera2D.cs @@ -0,0 +1,22 @@ +using System.Numerics; + +namespace SlatedGameToolkit.Framework.Graphics.Render +{ + public class Camera2D : Camera { + public new Vector2 Position { + get { + return new Vector2(base.Position.X, base.Position.Y); + } + + set { + base.Position = new Vector3(value, 0); + } + } + + public Camera2D() { + this.Orthographic = true; + this.Up = Vector3.UnitY; + this.LookAt = new Vector3(0, 0, 1); + } + } +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Graphics/Render/IRenderable.cs b/src/SlatedGameToolkit.Framework/Graphics/Render/IRenderable.cs index 77de1ca..a26f383 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Render/IRenderable.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Render/IRenderable.cs @@ -1,3 +1,4 @@ +using System.Drawing; using SlatedGameToolkit.Framework.Graphics.Meshes; using SlatedGameToolkit.Framework.Graphics.Textures; @@ -6,5 +7,6 @@ namespace SlatedGameToolkit.Framework.Graphics.Render public interface IRenderable : IMeshable { Texture Texture { get; } + Color Color { get; } } } \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Graphics/Render/Renderer.cs b/src/SlatedGameToolkit.Framework/Graphics/Render/Renderer.cs index f27c776..a538632 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Render/Renderer.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Render/Renderer.cs @@ -1,5 +1,8 @@ using System; using System.Drawing; +using System.Numerics; +using SlatedGameToolkit.Framework.Exceptions; +using SlatedGameToolkit.Framework.Graphics.Programs; using SlatedGameToolkit.Framework.Graphics.Textures; namespace SlatedGameToolkit.Framework.Graphics.Render @@ -13,8 +16,8 @@ namespace SlatedGameToolkit.Framework.Graphics.Render this.batch = batch; } - public Renderer() { - this.batch = new Batch(); + public Renderer(Camera camera, GLShaderProgram program, uint BatchVertexSize = 4096) { + this.batch = new Batch(camera, program, BatchVertexSize); } public void Dispose() @@ -22,14 +25,13 @@ namespace SlatedGameToolkit.Framework.Graphics.Render batch.Dispose(); } - public void Queue(IRenderable renderable, Color color) { + public void Queue(IRenderable renderable, Matrix4x4 modelsMatrix) { if (renderable.Texture != currentTexture) { if (batch.Batching) batch.End(); currentTexture = renderable.Texture; - currentTexture.Use(); - batch.Begin(currentTexture); + batch.Begin(currentTexture, modelsMatrix); } - batch.Add(renderable, color); + batch.Add(renderable, renderable.Color); } public void Render() { diff --git a/src/SlatedGameToolkit.Framework/Graphics/Render/Sprite2D.cs b/src/SlatedGameToolkit.Framework/Graphics/Render/Sprite2D.cs index b7223cc..6aff36f 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Render/Sprite2D.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Render/Sprite2D.cs @@ -1,3 +1,4 @@ +using System.Drawing; using SlatedGameToolkit.Framework.Graphics.Meshes; using SlatedGameToolkit.Framework.Graphics.Textures; @@ -6,7 +7,10 @@ namespace SlatedGameToolkit.Framework.Graphics.Render public class Sprite2D : RectangleMesh, IRenderable { public Texture Texture { get; private set; } - public Sprite2D(Texture texture) { + + public Color Color { get; private set; } + + public Sprite2D(Texture texture, Color color) { this.Texture = texture; this.textureCoords[0].X = -1; this.textureCoords[0].Y = -1; @@ -19,6 +23,8 @@ namespace SlatedGameToolkit.Framework.Graphics.Render this.textureCoords[3].X = -1; this.textureCoords[3].Y = 1; + + this.Color = color; } } } \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLFragmentShader.cs b/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLFragmentShader.cs index 432dd41..407a4ba 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLFragmentShader.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLFragmentShader.cs @@ -1,4 +1,6 @@ +using System.Text; using SlatedGameToolkit.Framework.Exceptions; +using SlatedGameToolkit.Framework.Graphics; namespace SlatedGameToolkit.Framework.Graphics.Shaders { @@ -9,15 +11,15 @@ namespace SlatedGameToolkit.Framework.Graphics.Shaders /// /// A string representing the GLSL code to run. public GLFragmentShader(string shader) : base() { - Handle = createShader(GLEnums.GL_FRAGMENT_SHADER); - shaderSource(Handle, 1, shader, null); + Handle = createShader(GLEnum.GL_FRAGMENT_SHADER); + shaderSource(Handle, 1, new string[] {shader}, null); compileShader(Handle); uint logLength; - string shaderLog; - getShaderLogInfo(Handle, 1024, out logLength, out shaderLog); + byte[] log = new byte[2048]; + getShaderInfoLog(Handle, (uint)log.Length, out logLength, log); if (logLength > 0) { Dispose(); - throw new OpenGLException(shaderLog); + throw new OpenGLException(Encoding.UTF8.GetString(log)); } OpenGLErrorException.CheckGLErrorStatus(); } diff --git a/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLShader.cs b/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLShader.cs index 7d71c49..03d17e9 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLShader.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLShader.cs @@ -2,6 +2,7 @@ using System; using System.Runtime.InteropServices; using SDL2; using SlatedGameToolkit.Framework.Exceptions; +using SlatedGameToolkit.Framework.Graphics; using SlatedGameToolkit.Framework.Graphics.Programs; using SlatedGameToolkit.Framework.Graphics.Window; @@ -9,35 +10,23 @@ namespace SlatedGameToolkit.Framework.Graphics.Shaders { public abstract class GLShader : IDisposable { private WindowContext context; - public UIntPtr Handle { get; private protected set; } + public virtual UIntPtr Handle { get; protected set; } protected GLCreateShader createShader; protected GLShaderSource shaderSource; protected GLCompileShader compileShader; - protected GLGetShaderLogInfo getShaderLogInfo; - protected GLGetAttribLocation getAttribLocation; + protected GLGetShaderInfoLog getShaderInfoLog; private GLDeleteShader deleteShader; public GLShader() { context = WindowContextsManager.CurrentWindowContext; - createShader = GLFunctionUtils.RetrieveGLDelegate("glCreateShader"); - shaderSource = GLFunctionUtils.RetrieveGLDelegate("glShaderSource"); - compileShader = GLFunctionUtils.RetrieveGLDelegate("glCompileShader"); - getShaderLogInfo = GLFunctionUtils.RetrieveGLDelegate("glGetShaderLogInfo"); - deleteShader = GLFunctionUtils.RetrieveGLDelegate("glDeleteShader"); - getAttribLocation = GLFunctionUtils.RetrieveGLDelegate("glGetAttribLocation"); + createShader = OpenGL.RetrieveGLDelegate("glCreateShader"); + shaderSource = OpenGL.RetrieveGLDelegate("glShaderSource"); + compileShader = OpenGL.RetrieveGLDelegate("glCompileShader"); + getShaderInfoLog = OpenGL.RetrieveGLDelegate("glGetShaderInfoLog"); + deleteShader = OpenGL.RetrieveGLDelegate("glDeleteShader"); } - /// - /// Gets the attribute location. - /// - /// The name of the attribute. - /// The attribute location index. - public int GetAttributeLocation(string attributeName) { - int index = getAttribLocation(Handle, attributeName); - OpenGLErrorException.CheckGLErrorStatus(); - return index; - } /// /// Disposes of the shader at the handle. diff --git a/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLVertexArraySet.cs b/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLVertexArraySet.cs index fc9635c..52001a2 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLVertexArraySet.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLVertexArraySet.cs @@ -1,6 +1,7 @@ using System; using System.Runtime.InteropServices; using SlatedGameToolkit.Framework.Exceptions; +using SlatedGameToolkit.Framework.Graphics; namespace SlatedGameToolkit.Framework.Graphics.Shaders { @@ -23,16 +24,16 @@ namespace SlatedGameToolkit.Framework.Graphics.Shaders public GLVertexArraySet(uint amount) { if (amount > int.MaxValue) throw new ArgumentOutOfRangeException("amount"); this.Count = (int)amount; - genBuffers = GLFunctionUtils.RetrieveGLDelegate("glGenBuffers"); - deleteBuffers = GLFunctionUtils.RetrieveGLDelegate("glDeleteBuffers"); - bindBuffer = GLFunctionUtils.RetrieveGLDelegate("glBindBuffer"); - genVertexArrays = GLFunctionUtils.RetrieveGLDelegate("glGenVertexArrays"); - bindVertexArray = GLFunctionUtils.RetrieveGLDelegate("glBindVertexArray"); - deleteVertexArrays = GLFunctionUtils.RetrieveGLDelegate("glDeleteVertexArrays"); - vertexAttribPointer = GLFunctionUtils.RetrieveGLDelegate("glVertexAttribPointer"); - enableVertexAttribArray = GLFunctionUtils.RetrieveGLDelegate("glEnableVertexAttribArray"); - disableVertexAttribArray = GLFunctionUtils.RetrieveGLDelegate("glDisableVertexAttribArray"); - bufferData = GLFunctionUtils.RetrieveGLDelegate("glBufferData"); + genBuffers = OpenGL.RetrieveGLDelegate("glGenBuffers"); + deleteBuffers = OpenGL.RetrieveGLDelegate("glDeleteBuffers"); + bindBuffer = OpenGL.RetrieveGLDelegate("glBindBuffer"); + genVertexArrays = OpenGL.RetrieveGLDelegate("glGenVertexArrays"); + bindVertexArray = OpenGL.RetrieveGLDelegate("glBindVertexArray"); + deleteVertexArrays = OpenGL.RetrieveGLDelegate("glDeleteVertexArrays"); + vertexAttribPointer = OpenGL.RetrieveGLDelegate("glVertexAttribPointer"); + enableVertexAttribArray = OpenGL.RetrieveGLDelegate("glEnableVertexAttribArray"); + disableVertexAttribArray = OpenGL.RetrieveGLDelegate("glDisableVertexAttribArray"); + bufferData = OpenGL.RetrieveGLDelegate("glBufferData"); arrayBufferHandles = new UIntPtr[amount]; vertexArrayHandles = new UIntPtr[amount]; indexArrayHandles = new UIntPtr[amount]; @@ -47,20 +48,20 @@ namespace SlatedGameToolkit.Framework.Graphics.Shaders public void Use(uint index) { bindVertexArray(vertexArrayHandles[index]); OpenGLErrorException.CheckGLErrorStatus(); - bindBuffer(GLEnums.GL_ELEMENT_ARRAY_BUFFER, indexArrayHandles[index]); - bindBuffer(GLEnums.GL_ARRAY_BUFFER, arrayBufferHandles[index]); + bindBuffer(GLEnum.GL_ELEMENT_ARRAY_BUFFER, indexArrayHandles[index]); + bindBuffer(GLEnum.GL_ARRAY_BUFFER, arrayBufferHandles[index]); OpenGLErrorException.CheckGLErrorStatus(); } public unsafe void BufferVertices(uint index, float[] data, bool dynamic) { Use(index); - bufferData(GLEnums.GL_ARRAY_BUFFER, (uint) (sizeof(float) * data.Length), data, dynamic ? GLEnums.GL_DYNAMIC_DRAW : GLEnums.GL_STATIC_DRAW); + bufferData(GLEnum.GL_ARRAY_BUFFER, (uint) (sizeof(float) * data.Length), data, dynamic ? GLEnum.GL_DYNAMIC_DRAW : GLEnum.GL_STATIC_DRAW); OpenGLErrorException.CheckGLErrorStatus(); } public unsafe void BufferIndices(uint index, uint[] data, bool dynamic) { Use(index); - bufferData(GLEnums.GL_ELEMENT_ARRAY_BUFFER, (uint) (sizeof(float) * data.Length), data, dynamic ? GLEnums.GL_DYNAMIC_DRAW : GLEnums.GL_STATIC_DRAW); + bufferData(GLEnum.GL_ELEMENT_ARRAY_BUFFER, (uint) (sizeof(float) * data.Length), data, dynamic ? GLEnum.GL_DYNAMIC_DRAW : GLEnum.GL_STATIC_DRAW); OpenGLErrorException.CheckGLErrorStatus(); } @@ -75,7 +76,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Shaders Use(bufferIndex); foreach (VertexAttributeDefinition definition in definitions) { - vertexAttribPointer(definition.attributeIndex, definition.size, GLEnums.GL_FLOAT, false, definition.stride, definition.offset); + vertexAttribPointer(definition.attributeIndex, definition.size, GLEnum.GL_FLOAT, false, definition.stride, definition.offset); OpenGLErrorException.CheckGLErrorStatus(); if (enableAttributes) enableVertexAttribArray(definition.attributeIndex); } diff --git a/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLVertexShader.cs b/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLVertexShader.cs index 5967752..89e0ef9 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLVertexShader.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Shaders/GLVertexShader.cs @@ -1,3 +1,4 @@ +using System.Text; using SlatedGameToolkit.Framework.Exceptions; namespace SlatedGameToolkit.Framework.Graphics.Shaders @@ -9,15 +10,15 @@ namespace SlatedGameToolkit.Framework.Graphics.Shaders /// /// A string representing the GLSL code. public GLVertexShader(string shader) : base() { - Handle = createShader(GLEnums.GL_VERTEX_SHADER); - shaderSource(Handle, 1, shader, null); + Handle = createShader(GLEnum.GL_VERTEX_SHADER); + shaderSource(Handle, 1, new string[] {shader}, null); compileShader(Handle); uint logLength; - string shaderLog; - getShaderLogInfo(Handle, 1024, out logLength, out shaderLog); + byte[] log = new byte[2048]; + getShaderInfoLog(Handle, (uint)log.Length, out logLength, log); if (logLength > 0) { Dispose(); - throw new OpenGLException(shaderLog); + throw new OpenGLException(Encoding.UTF8.GetString(log)); } OpenGLErrorException.CheckGLErrorStatus(); } diff --git a/src/SlatedGameToolkit.Framework/Graphics/Shaders/NormalFragmentShader.cs b/src/SlatedGameToolkit.Framework/Graphics/Shaders/NormalFragmentShader.cs new file mode 100644 index 0000000..3718113 --- /dev/null +++ b/src/SlatedGameToolkit.Framework/Graphics/Shaders/NormalFragmentShader.cs @@ -0,0 +1,21 @@ +using System; +using System.IO; +using System.Reflection; + +namespace SlatedGameToolkit.Framework.Graphics.Shaders +{ + public class NormalFragmentShader : GLShader + { + private GLFragmentShader shader; + public NormalFragmentShader() { + using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SlatedGameToolkit.Framework.Resources.default.frag")) + { + using (StreamReader reader = new StreamReader(stream)) + { + shader = new GLFragmentShader(reader.ReadToEnd()); + } + } + this.Handle = shader.Handle; + } + } +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Graphics/Shaders/NormalVertexShader.cs b/src/SlatedGameToolkit.Framework/Graphics/Shaders/NormalVertexShader.cs new file mode 100644 index 0000000..aa071a5 --- /dev/null +++ b/src/SlatedGameToolkit.Framework/Graphics/Shaders/NormalVertexShader.cs @@ -0,0 +1,20 @@ +using System; +using System.IO; +using System.Reflection; + +namespace SlatedGameToolkit.Framework.Graphics.Shaders { + public class NormalVertexShader : GLShader + { + private GLVertexShader shader; + + public NormalVertexShader() { + using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SlatedGameToolkit.Framework.Resources.default.vert")) + { + using (StreamReader reader = new StreamReader(stream)) { + shader = new GLVertexShader(reader.ReadToEnd()); + } + } + Handle = shader.Handle; + } + } +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Graphics/Textures/GLTexture2DSet.cs b/src/SlatedGameToolkit.Framework/Graphics/Textures/GLTexture2DSet.cs index 3b5156b..661bf67 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Textures/GLTexture2DSet.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Textures/GLTexture2DSet.cs @@ -15,23 +15,23 @@ namespace SlatedGameToolkit.Framework.Graphics private GLDeleteTextures deleteTextures; private GLTexImage2D texImage2D; private GLBindTexture bindTexture; - private GLGenerateMipMap generateMipMap; + private GLGenerateMipmap generateMipmap; private readonly UIntPtr[] handle; public GLTexture2DSet(TextureData[] textureDatas, bool linear = false, bool mipmap = false) { - genTextures = GLFunctionUtils.RetrieveGLDelegate("glGenTextures"); - deleteTextures = GLFunctionUtils.RetrieveGLDelegate("glDeleteTextures"); - bindTexture = GLFunctionUtils.RetrieveGLDelegate("glBindTexture"); - texParameteri = GLFunctionUtils.RetrieveGLDelegate("glTexParameteri"); - texParameterfv = GLFunctionUtils.RetrieveGLDelegate("glTexParameterfv"); - texImage2D = GLFunctionUtils.RetrieveGLDelegate("glTexImage2D"); - generateMipMap = GLFunctionUtils.RetrieveGLDelegate("glGenerateMipMap"); + genTextures = OpenGL.RetrieveGLDelegate("glGenTextures"); + deleteTextures = OpenGL.RetrieveGLDelegate("glDeleteTextures"); + bindTexture = OpenGL.RetrieveGLDelegate("glBindTexture"); + texParameteri = OpenGL.RetrieveGLDelegate("glTexParameteri"); + texParameterfv = OpenGL.RetrieveGLDelegate("glTexParameterfv"); + texImage2D = OpenGL.RetrieveGLDelegate("glTexImage2D"); + generateMipmap = OpenGL.RetrieveGLDelegate("glGenerateMipmap"); handle = new UIntPtr[textureDatas.Length]; genTextures((uint)textureDatas.Length, handle); for (uint i = 0; i < textureDatas.Length; i++) { Setup(i, textureDatas[i]); } - bindTexture(GLEnums.GL_TEXTURE_2D, UIntPtr.Zero); + bindTexture(GLEnum.GL_TEXTURE_2D, UIntPtr.Zero); OpenGLErrorException.CheckGLErrorStatus(); this.Count = textureDatas.Length; @@ -39,8 +39,10 @@ namespace SlatedGameToolkit.Framework.Graphics private void Setup(uint index, TextureData textureData) { Bind(index); - texImage2D(GLEnums.GL_TEXTURE_2D, 0, (int)GLEnums.GL_RGBA, textureData.width, textureData.height, 0, GLEnums.GL_RGBA, GLEnums.GL_UNSIGNED_BYTE, textureData.data); - generateMipMap(GLEnums.GL_TEXTURE_2D); + texImage2D(GLEnum.GL_TEXTURE_2D, 0, (int)GLEnum.GL_RGBA, textureData.width, textureData.height, 0, GLEnum.GL_RGBA, GLEnum.GL_UNSIGNED_BYTE, textureData.data); + OpenGLErrorException.CheckGLErrorStatus(); + generateMipmap(GLEnum.GL_TEXTURE_2D); + OpenGLErrorException.CheckGLErrorStatus(); } /// @@ -50,12 +52,12 @@ namespace SlatedGameToolkit.Framework.Graphics /// The index of the texture. /// Whether or not to have linear filtering. /// Whether or not to use MipMap - public void SetProperties(uint index, GLEnums min, GLEnums mag) { + public void SetProperties(uint index, GLEnum min, GLEnum mag) { Bind(index); - texParameteri(GLEnums.GL_TEXTURE_2D, GLEnums.GL_TEXTURE_WRAP_S, (int)GLEnums.GL_CLAMP_TO_EDGE); - texParameteri(GLEnums.GL_TEXTURE_2D, GLEnums.GL_TEXTURE_WRAP_T, (int)GLEnums.GL_CLAMP_TO_EDGE); - texParameteri(GLEnums.GL_TEXTURE_2D, GLEnums.GL_TEXTURE_MIN_FILTER, (int) min); - texParameteri(GLEnums.GL_TEXTURE_2D, GLEnums.GL_TEXTURE_MAG_FILTER, (int) mag); + texParameteri(GLEnum.GL_TEXTURE_2D, GLEnum.GL_TEXTURE_WRAP_S, (int)GLEnum.GL_CLAMP_TO_EDGE); + texParameteri(GLEnum.GL_TEXTURE_2D, GLEnum.GL_TEXTURE_WRAP_T, (int)GLEnum.GL_CLAMP_TO_EDGE); + texParameteri(GLEnum.GL_TEXTURE_2D, GLEnum.GL_TEXTURE_MIN_FILTER, (int) min); + texParameteri(GLEnum.GL_TEXTURE_2D, GLEnum.GL_TEXTURE_MAG_FILTER, (int) mag); } /// @@ -63,8 +65,8 @@ namespace SlatedGameToolkit.Framework.Graphics /// /// The index of the texture in this set. public void Bind(uint index) { - bindTexture(GLEnums.GL_TEXTURE_2D, handle[index]); - + bindTexture(GLEnum.GL_TEXTURE_2D, handle[index]); + OpenGLErrorException.CheckGLErrorStatus(); } public void Dispose() diff --git a/src/SlatedGameToolkit.Framework/Graphics/Textures/Texture.cs b/src/SlatedGameToolkit.Framework/Graphics/Textures/Texture.cs index e42d524..5979a84 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Textures/Texture.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Textures/Texture.cs @@ -1,3 +1,4 @@ +using SlatedGameToolkit.Framework.Exceptions; using SlatedGameToolkit.Framework.Loader; namespace SlatedGameToolkit.Framework.Graphics.Textures @@ -15,6 +16,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Textures public Texture(TextureData textureData, bool linear = true, bool mipmap = true) { TextureData[] textureDatas = new TextureData[] {textureData}; this.glTexture2DSet = new GLTexture2DSet(textureDatas, linear, mipmap); + OpenGLErrorException.CheckGLErrorStatus(); this.index = 0; } diff --git a/src/SlatedGameToolkit.Framework/Graphics/Window/WindowContext.cs b/src/SlatedGameToolkit.Framework/Graphics/Window/WindowContext.cs index e203383..88e3ec0 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Window/WindowContext.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Window/WindowContext.cs @@ -92,18 +92,18 @@ namespace SlatedGameToolkit.Framework.Graphics.Window WindowContext actual = WindowContextsManager.CurrentWindowContext; bool diff = false; if (actual != this) { - WindowContextsManager.CurrentWindowContext = this; + MakeCurrent(); diff = true; } bool vSync = SDL.SDL_GL_GetSwapInterval() != 0; - if (diff) WindowContextsManager.CurrentWindowContext = actual; + if (diff) actual.MakeCurrent(); return vSync; } set { WindowContext actual = WindowContextsManager.CurrentWindowContext; bool diff = false; if (actual != this) { - WindowContextsManager.CurrentWindowContext = this; + MakeCurrent(); diff = true; } if (SDL.SDL_GL_SetSwapInterval(value ? -1 : 0) < 0) { @@ -111,7 +111,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Window throw new OptionalSDLException(); } } - if (diff) WindowContextsManager.CurrentWindowContext = actual; + if (diff) actual.MakeCurrent(); } } @@ -271,10 +271,10 @@ namespace SlatedGameToolkit.Framework.Graphics.Window throw new FrameworkSDLException(); } - clear = GLFunctionUtils.RetrieveGLDelegate("glClear"); - clearColour = GLFunctionUtils.RetrieveGLDelegate("glClearColor"); - viewport = GLFunctionUtils.RetrieveGLDelegate("glViewport"); - getError = GLFunctionUtils.RetrieveGLDelegate("glGetError"); + clear = OpenGL.RetrieveGLDelegate("glClear"); + clearColour = OpenGL.RetrieveGLDelegate("glClearColor"); + viewport = OpenGL.RetrieveGLDelegate("glViewport"); + getError = OpenGL.RetrieveGLDelegate("glGetError"); if (specialRegions) { if (SDL.SDL_SetWindowHitTest(windowHandle, SpecialRegionHit, IntPtr.Zero) < 0) { @@ -283,7 +283,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Window } WindowContextsManager.RegisterWindow(this); - WindowContextsManager.CurrentWindowContext = this; + MakeCurrent(); Vector2 drawable = GetDrawableDimensions(); viewport(0, 0, (int)drawable.X, (int)drawable.Y); @@ -336,9 +336,10 @@ namespace SlatedGameToolkit.Framework.Graphics.Window /// There can only be one window context active at any given time. /// public void MakeCurrent() { - - SDL.SDL_GL_MakeCurrent(windowHandle, glContextHandle); - WindowContextsManager.CurrentWindowContext = this; + if (WindowContextsManager.CurrentWindowContext != this) { + SDL.SDL_GL_MakeCurrent(windowHandle, glContextHandle); + WindowContextsManager.current = this; + } } /// diff --git a/src/SlatedGameToolkit.Framework/Graphics/Window/WindowContextsManager.cs b/src/SlatedGameToolkit.Framework/Graphics/Window/WindowContextsManager.cs index 291bafb..93e2b77 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Window/WindowContextsManager.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Window/WindowContextsManager.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace SlatedGameToolkit.Framework.Graphics.Window { public static class WindowContextsManager { - private static WindowContext current; + internal static WindowContext current; /// /// The current window context. @@ -13,13 +13,6 @@ namespace SlatedGameToolkit.Framework.Graphics.Window get { return current; } - - set { - if (current != value) { - current = value; - value.MakeCurrent(); - } - } } private static Dictionary existingWindows = new Dictionary(); diff --git a/src/SlatedGameToolkit.Framework/Loader/AssetManager.cs b/src/SlatedGameToolkit.Framework/Loader/AssetManager.cs index 4702514..fef2a15 100644 --- a/src/SlatedGameToolkit.Framework/Loader/AssetManager.cs +++ b/src/SlatedGameToolkit.Framework/Loader/AssetManager.cs @@ -7,7 +7,7 @@ namespace SlatedGameToolkit.Framework.Loader { public class AssetManager : IDisposable { private readonly object assetThreadLock = new object(); private Thread thread; - private ConcurrentQueue loadables; + private ConcurrentQueue> loadables; private volatile bool load; public bool Complete { get { @@ -17,7 +17,7 @@ namespace SlatedGameToolkit.Framework.Loader { private ConcurrentDictionary assets; public ConcurrentDictionary PathModifiers {get; private set; } public AssetManager() { - this.loadables = new ConcurrentQueue(); + this.loadables = new ConcurrentQueue>(); this.assets = new ConcurrentDictionary(); this.PathModifiers = new ConcurrentDictionary(); thread = new Thread(Process); @@ -32,14 +32,14 @@ namespace SlatedGameToolkit.Framework.Loader { /// The file name of the loadable is the one the loadable is saved under. /// /// The loadable. - public void QueueLoad(ILoadable loadable) { + public void QueueLoad(ILoadable loadable) { loadables.Enqueue(loadable); } private void Process() { lock (assetThreadLock) { - ILoadable loadable; + ILoadable loadable; while (load) { while (loadables.TryDequeue(out loadable)) { Load(loadable); @@ -53,7 +53,7 @@ namespace SlatedGameToolkit.Framework.Loader { /// Loads the loadable and stores it under the filename given to the loadable. /// /// The loadable to load. - public void Load(ILoadable loadable) { + public void Load(ILoadable loadable) { string name = loadable.FileName; assets[name] = loadable.Load(PathModifiers[loadable.GetType()]); } diff --git a/src/SlatedGameToolkit.Framework/Loader/ILoadable.cs b/src/SlatedGameToolkit.Framework/Loader/ILoadable.cs index df1e7c6..99521ef 100644 --- a/src/SlatedGameToolkit.Framework/Loader/ILoadable.cs +++ b/src/SlatedGameToolkit.Framework/Loader/ILoadable.cs @@ -11,7 +11,7 @@ namespace SlatedGameToolkit.Framework.Loader /// A loader is to load an asset the game uses. /// It is created whenever the asset needs to be loaded with a string representing the path to the file to actually load. /// - public interface ILoadable + public interface ILoadable where UseableT : IAssetUseable { /// /// The name of the file to load. @@ -26,6 +26,6 @@ namespace SlatedGameToolkit.Framework.Loader /// Modifies the path. May be null. Default is null. /// The loadable type. /// The loadable type. - IAssetUseable Load(PathModifier pathModifier = null); + UseableT Load(PathModifier pathModifier = null); } } \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Loader/TextureLoader.cs b/src/SlatedGameToolkit.Framework/Loader/TextureLoader.cs index 37eb439..4c97591 100644 --- a/src/SlatedGameToolkit.Framework/Loader/TextureLoader.cs +++ b/src/SlatedGameToolkit.Framework/Loader/TextureLoader.cs @@ -7,22 +7,22 @@ using SlatedGameToolkit.Framework.Loader; namespace SlatedGameToolkit.Framework.Loader { - public class TextureLoader : ILoadable + public class TextureLoader : ILoadable { public string FileName {get; private set; } public TextureLoader(string path) { this.FileName = path; } - public IAssetUseable Load(PathModifier pathModifier = null) + public Texture Load(PathModifier pathModifier = null) { - IntPtr ptr = SDL_image.IMG_Load(pathModifier(FileName)); - if (ptr == null) throw new FrameworkSDLException(); + IntPtr ptr = SDL_image.IMG_Load(pathModifier == null ? FileName : pathModifier(FileName)); + if (ptr.Equals(IntPtr.Zero)) throw new FrameworkSDLException(); SDL.SDL_Surface surface = Marshal.PtrToStructure(ptr); TextureData textureData = new TextureData(); - byte[] data = new byte[surface.pitch * surface.h]; - Marshal.Copy(surface.pixels, data, 0, data.Length); - IAssetUseable useable = new Texture(textureData); + textureData.data = new byte[surface.pitch * surface.h]; + Marshal.Copy(surface.pixels, textureData.data, 0, textureData.data.Length); + Texture useable = new Texture(textureData); return useable; } } diff --git a/src/SlatedGameToolkit.Framework/Resources/default.frag b/src/SlatedGameToolkit.Framework/Resources/default.frag new file mode 100644 index 0000000..f7ad5c1 --- /dev/null +++ b/src/SlatedGameToolkit.Framework/Resources/default.frag @@ -0,0 +1,11 @@ +#version 330 core +out vec4 outputColor; + +in vec2 texCoord; +in vec4 color; +uniform sampler2D texture0; + +void main() +{ + outputColor = texture(texture0, texCoord) * color; +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Resources/default.vert b/src/SlatedGameToolkit.Framework/Resources/default.vert new file mode 100644 index 0000000..d98073a --- /dev/null +++ b/src/SlatedGameToolkit.Framework/Resources/default.vert @@ -0,0 +1,17 @@ +#version 330 core +in vec3 aPosition; +in vec4 aColor; +in vec2 aTexCoord; +uniform mat4 models; +uniform mat4 view; +uniform mat4 projection; +out vec2 texCoord; +out vec4 color; + +void main() +{ + texCoord = aTexCoord; + color = aColor; + + gl_Position = projection * view * models * vec4(aPosition, 1.0f); +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/SlatedGameToolkit.Framework.csproj b/src/SlatedGameToolkit.Framework/SlatedGameToolkit.Framework.csproj index b926bd5..ba806ab 100644 --- a/src/SlatedGameToolkit.Framework/SlatedGameToolkit.Framework.csproj +++ b/src/SlatedGameToolkit.Framework/SlatedGameToolkit.Framework.csproj @@ -10,4 +10,7 @@ + + + diff --git a/src/SlatedGameToolkit.Framework/StateSystem/Manager.cs b/src/SlatedGameToolkit.Framework/StateSystem/StateManager.cs similarity index 85% rename from src/SlatedGameToolkit.Framework/StateSystem/Manager.cs rename to src/SlatedGameToolkit.Framework/StateSystem/StateManager.cs index 15ea52c..befd9b3 100644 --- a/src/SlatedGameToolkit.Framework/StateSystem/Manager.cs +++ b/src/SlatedGameToolkit.Framework/StateSystem/StateManager.cs @@ -2,13 +2,14 @@ using System; using System.Collections.Generic; using System.Drawing; using System.Threading; +using SlatedGameToolkit.Framework.Exceptions; using SlatedGameToolkit.Framework.Graphics; using SlatedGameToolkit.Framework.Graphics.Window; using SlatedGameToolkit.Framework.StateSystem.States; namespace SlatedGameToolkit.Framework.StateSystem { - public sealed class Manager : IDisposable { + public sealed class StateManager : IDisposable { public Thread thread; public Color backgroundColour; private IState currentState; @@ -22,14 +23,17 @@ namespace SlatedGameToolkit.Framework.StateSystem /// /// The name of the initial state. /// The initial set of game states to be added. - internal Manager(IState initialState) { + internal StateManager() { backgroundColour = Color.Orange; + this.states = new Dictionary(); + } + + internal void Initialize(IState initialState) { if (initialState == null) throw new ArgumentNullException("initialState"); thread = Thread.CurrentThread; - this.states = new Dictionary(); - addState(initialState); currentState = initialState; + addState(initialState); } internal void update(double delta) { @@ -44,8 +48,10 @@ namespace SlatedGameToolkit.Framework.StateSystem internal void render(double delta) { WindowContext windowContext = WindowContextsManager.CurrentWindowContext; - windowContext.clearColour(backgroundColour.R / 254f, backgroundColour.G / 254f, backgroundColour.B / 254f); - windowContext.clear(GLEnums.GL_COLOR_BUFFER_BIT | GLEnums.GL_DEPTH_STENCIL); + windowContext.clearColour((float)backgroundColour.R / byte.MaxValue, (float)backgroundColour.G / byte.MaxValue, (float)backgroundColour.B / byte.MaxValue); + OpenGLErrorException.CheckGLErrorStatus(); + windowContext.clear(GLEnum.GL_COLOR_BUFFER_BIT | GLEnum.GL_DEPTH_BUFFER_BIT); + OpenGLErrorException.CheckGLErrorStatus(); currentState.Render(delta); windowContext.SwapBuffer(); } @@ -87,8 +93,8 @@ namespace SlatedGameToolkit.Framework.StateSystem public bool addState(IState state) { if (thread != Thread.CurrentThread) throw new ThreadStateException("Cannot add a state from a different thread."); try { - GameEngine.Logger.Debug("Adding state: " + state.getName()); - this.states.Add(state.getName(), state); + GameEngine.Logger.Debug("Adding state: " + state.getName()); + this.states.Add(state.getName(), state); } catch (ArgumentException) { return false; } @@ -108,7 +114,12 @@ namespace SlatedGameToolkit.Framework.StateSystem if (states[name] == currentState) return false; IState state = states[name]; GameEngine.Logger.Debug("Removing state: " + name); - state.Deinitialize(); + try { + state.Deinitialize(); + } catch (Exception e) { + GameEngine.Logger.Error(e.ToString()); + GameEngine.Logger.Error("Failed to deinitialize state: " + state.getName()); + } return states.Remove(name); } diff --git a/src/SlatedGameToolkit.Framework/StateSystem/States/IState.cs b/src/SlatedGameToolkit.Framework/StateSystem/States/IState.cs index f6f3260..0727d37 100644 --- a/src/SlatedGameToolkit.Framework/StateSystem/States/IState.cs +++ b/src/SlatedGameToolkit.Framework/StateSystem/States/IState.cs @@ -44,7 +44,7 @@ namespace SlatedGameToolkit.Framework.StateSystem.States /// Should be used to set up this state. /// /// The manager that made this call. - void Initialize(Manager manager); + void Initialize(StateManager manager); /// /// The name of this state. diff --git a/src/SlatedGameToolkit.Tools/System/CommandMap.cs b/src/SlatedGameToolkit.Tools/CommandSystem/CommandMap.cs similarity index 95% rename from src/SlatedGameToolkit.Tools/System/CommandMap.cs rename to src/SlatedGameToolkit.Tools/CommandSystem/CommandMap.cs index f62a3da..839aa52 100644 --- a/src/SlatedGameToolkit.Tools/System/CommandMap.cs +++ b/src/SlatedGameToolkit.Tools/CommandSystem/CommandMap.cs @@ -1,9 +1,9 @@ using System; using System.Collections; using System.Collections.Generic; -using SlatedGameToolkit.Tools.System.Interaction; +using SlatedGameToolkit.Tools.CommandSystem.Interaction; -namespace SlatedGameToolkit.Tools.System +namespace SlatedGameToolkit.Tools.CommandSystem { public class CommandMap : ICollection, IDisposable { Dictionary invocations; diff --git a/src/SlatedGameToolkit.Tools/System/CommandProcessor.cs b/src/SlatedGameToolkit.Tools/CommandSystem/CommandProcessor.cs similarity index 60% rename from src/SlatedGameToolkit.Tools/System/CommandProcessor.cs rename to src/SlatedGameToolkit.Tools/CommandSystem/CommandProcessor.cs index 733375f..224a676 100644 --- a/src/SlatedGameToolkit.Tools/System/CommandProcessor.cs +++ b/src/SlatedGameToolkit.Tools/CommandSystem/CommandProcessor.cs @@ -1,22 +1,19 @@ using System; -using SlatedGameToolkit.Tools.System.Interaction; +using SlatedGameToolkit.Tools.CommandSystem.Interaction; -namespace SlatedGameToolkit.Tools.System +namespace SlatedGameToolkit.Tools.CommandSystem { public class CommandProcessor { - private string generalHelpMessage; CommandMap commandMap; /// /// The general help is the string that is printed when the input is not understood. /// {input} in the string is replaced with the user input. /// - /// /// - public CommandProcessor(string generalHelp, CommandMap commands) { + public CommandProcessor(CommandMap commands) { this.commandMap = commands; - this.generalHelpMessage = generalHelp; } public void Process(IInteractable interactable) { string message = interactable.Listen(); @@ -27,11 +24,12 @@ namespace SlatedGameToolkit.Tools.System if (invocable != null) { string[] args = new string[splitMessage.Length - 1]; Array.Copy(splitMessage, 1, args, 0, splitMessage.Length - 1); - if (invocable.Execute(interactable, args)) { - return; + if (!invocable.Execute(interactable, args)) { + interactable.Tell(string.Format("The command \"{0}\" was recognized, but arguments were incorrect. Please refer to Please type \"help {0}\" for more information.", invocation)); } + return; } - interactable.Tell(generalHelpMessage.Replace("{input}", invocation)); + interactable.Tell(string.Format("The input \"{0}\" was not understood. Please type \"help\" for more information.", invocation)); } } } \ No newline at end of file diff --git a/src/SlatedGameToolkit.Tools/CommandSystem/Exceptions/FatalUsageException.cs b/src/SlatedGameToolkit.Tools/CommandSystem/Exceptions/FatalUsageException.cs new file mode 100644 index 0000000..228260d --- /dev/null +++ b/src/SlatedGameToolkit.Tools/CommandSystem/Exceptions/FatalUsageException.cs @@ -0,0 +1,14 @@ +using System; +using System.Runtime.Serialization; + +namespace SlatedGameToolkit.Tools.CommandSystem.Exceptions +{ + [Serializable] + public class FatalUsageException : Exception + { + public FatalUsageException() { } + public FatalUsageException(string message) : base(message) { } + public FatalUsageException(string message, Exception inner) : base(message, inner) { } + protected FatalUsageException(SerializationInfo info, StreamingContext context) : base(info, context) { } + } +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Tools/System/IInvocable.cs b/src/SlatedGameToolkit.Tools/CommandSystem/IInvocable.cs similarity index 93% rename from src/SlatedGameToolkit.Tools/System/IInvocable.cs rename to src/SlatedGameToolkit.Tools/CommandSystem/IInvocable.cs index f27f63c..3e540f0 100644 --- a/src/SlatedGameToolkit.Tools/System/IInvocable.cs +++ b/src/SlatedGameToolkit.Tools/CommandSystem/IInvocable.cs @@ -1,7 +1,7 @@ using System; -using SlatedGameToolkit.Tools.System.Interaction; +using SlatedGameToolkit.Tools.CommandSystem.Interaction; -namespace SlatedGameToolkit.Tools.System +namespace SlatedGameToolkit.Tools.CommandSystem { public interface IInvocable : IDisposable { diff --git a/src/SlatedGameToolkit.Tools/System/Interaction/ConsoleInteraction.cs b/src/SlatedGameToolkit.Tools/CommandSystem/Interaction/ConsoleInteraction.cs similarity index 89% rename from src/SlatedGameToolkit.Tools/System/Interaction/ConsoleInteraction.cs rename to src/SlatedGameToolkit.Tools/CommandSystem/Interaction/ConsoleInteraction.cs index b8f0064..ae97af1 100644 --- a/src/SlatedGameToolkit.Tools/System/Interaction/ConsoleInteraction.cs +++ b/src/SlatedGameToolkit.Tools/CommandSystem/Interaction/ConsoleInteraction.cs @@ -1,6 +1,6 @@ using System; -namespace SlatedGameToolkit.Tools.System.Interaction +namespace SlatedGameToolkit.Tools.CommandSystem.Interaction { public class ConsoleInteraction : IInteractable { diff --git a/src/SlatedGameToolkit.Tools/System/Interaction/IInteractable.cs b/src/SlatedGameToolkit.Tools/CommandSystem/Interaction/IInteractable.cs similarity index 69% rename from src/SlatedGameToolkit.Tools/System/Interaction/IInteractable.cs rename to src/SlatedGameToolkit.Tools/CommandSystem/Interaction/IInteractable.cs index 1530574..1397ddc 100644 --- a/src/SlatedGameToolkit.Tools/System/Interaction/IInteractable.cs +++ b/src/SlatedGameToolkit.Tools/CommandSystem/Interaction/IInteractable.cs @@ -1,4 +1,4 @@ -namespace SlatedGameToolkit.Tools.System.Interaction +namespace SlatedGameToolkit.Tools.CommandSystem.Interaction { public interface IInteractable { diff --git a/src/SlatedGameToolkit.Tools/CommandSystem/Interaction/SingleConsoleInteraction.cs b/src/SlatedGameToolkit.Tools/CommandSystem/Interaction/SingleConsoleInteraction.cs new file mode 100644 index 0000000..e6bec0f --- /dev/null +++ b/src/SlatedGameToolkit.Tools/CommandSystem/Interaction/SingleConsoleInteraction.cs @@ -0,0 +1,30 @@ +using System; +using SlatedGameToolkit.Tools.CommandSystem.Exceptions; + +namespace SlatedGameToolkit.Tools.CommandSystem.Interaction +{ + public class SingleConsoleInteraction : IInteractable + { + private bool interacted; + private string oneTime; + public SingleConsoleInteraction(string oneTime) { + this.oneTime = oneTime; + } + public string Listen() + { + if (interacted) throw new FatalUsageException("Command attempted to request for more information. This generally occurs if the command being ran requires more user input."); + interacted = true; + return oneTime; + } + + public void Separate() + { + Console.WriteLine(); + } + + public void Tell(string message) + { + Console.WriteLine(message); + } + } +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Tools/Commands/GraphicalPlaygroundCommand.cs b/src/SlatedGameToolkit.Tools/Commands/GraphicalPlaygroundCommand.cs index c6d32ae..83bb3d8 100644 --- a/src/SlatedGameToolkit.Tools/Commands/GraphicalPlaygroundCommand.cs +++ b/src/SlatedGameToolkit.Tools/Commands/GraphicalPlaygroundCommand.cs @@ -1,8 +1,8 @@ using SlatedGameToolkit.Framework; using SlatedGameToolkit.Framework.StateSystem; -using SlatedGameToolkit.Tools.System; -using SlatedGameToolkit.Tools.System.Interaction; -using SlatedGameToolkit.Tools.Utilities.GraphicalPlayground; +using SlatedGameToolkit.Tools.CommandSystem; +using SlatedGameToolkit.Tools.CommandSystem.Interaction; +using SlatedGameToolkit.Tools.Utilities.Playground; namespace SlatedGameToolkit.Tools.Commands { diff --git a/src/SlatedGameToolkit.Tools/Commands/HelpCommand.cs b/src/SlatedGameToolkit.Tools/Commands/HelpCommand.cs index f3a23f5..df4b296 100644 --- a/src/SlatedGameToolkit.Tools/Commands/HelpCommand.cs +++ b/src/SlatedGameToolkit.Tools/Commands/HelpCommand.cs @@ -1,7 +1,7 @@ using System; using System.Text; -using SlatedGameToolkit.Tools.System; -using SlatedGameToolkit.Tools.System.Interaction; +using SlatedGameToolkit.Tools.CommandSystem; +using SlatedGameToolkit.Tools.CommandSystem.Interaction; namespace SlatedGameToolkit.Tools.Commands { diff --git a/src/SlatedGameToolkit.Tools/Commands/ListEmbeddedResourcesCommand.cs b/src/SlatedGameToolkit.Tools/Commands/ListEmbeddedResourcesCommand.cs new file mode 100644 index 0000000..f1958dd --- /dev/null +++ b/src/SlatedGameToolkit.Tools/Commands/ListEmbeddedResourcesCommand.cs @@ -0,0 +1,42 @@ +using System.Reflection; +using SlatedGameToolkit.Framework; +using SlatedGameToolkit.Tools.CommandSystem; +using SlatedGameToolkit.Tools.CommandSystem.Interaction; + +namespace SlatedGameToolkit.Tools.Commands +{ + public class ListEmbeddedResourcesCommand : IInvocable + { + private string[] invokers = new string[] {"GetEmbedded"}; + public void Dispose() + { + } + + public bool Execute(IInteractable interactable, string[] args) + { + Assembly assembly = Assembly.GetAssembly(typeof(GameEngine)); + string[] embeddedFiles = assembly.GetManifestResourceNames(); + interactable.Tell("Loaded embedded files:"); + foreach (string fileName in embeddedFiles) + { + interactable.Tell(fileName); + } + return true; + } + + public string getDescription() + { + return "Returns a list of embedded resources in the given assembly."; + } + + public string[] GetInvokers() + { + return invokers; + } + + public string getUsage(string arg) + { + return "Usage: \"GetEmbedded\" to retrieve a list of embedded files in the framework and tools."; + } + } +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Tools/Commands/StopCommand.cs b/src/SlatedGameToolkit.Tools/Commands/StopCommand.cs index b189519..d54fd63 100644 --- a/src/SlatedGameToolkit.Tools/Commands/StopCommand.cs +++ b/src/SlatedGameToolkit.Tools/Commands/StopCommand.cs @@ -1,5 +1,5 @@ -using SlatedGameToolkit.Tools.System; -using SlatedGameToolkit.Tools.System.Interaction; +using SlatedGameToolkit.Tools.CommandSystem; +using SlatedGameToolkit.Tools.CommandSystem.Interaction; namespace SlatedGameToolkit.Tools.Commands { diff --git a/src/SlatedGameToolkit.Tools/Program.cs b/src/SlatedGameToolkit.Tools/Program.cs index acc9ac5..4f9a62d 100644 --- a/src/SlatedGameToolkit.Tools/Program.cs +++ b/src/SlatedGameToolkit.Tools/Program.cs @@ -1,36 +1,43 @@ using System; using System.Reflection; +using System.Text; using SlatedGameToolkit.Tools.Commands; -using SlatedGameToolkit.Tools.System; -using SlatedGameToolkit.Tools.System.Interaction; +using SlatedGameToolkit.Tools.CommandSystem; +using SlatedGameToolkit.Tools.CommandSystem.Interaction; namespace SlatedGameToolkit.Tools { class Program { - static private bool running; + static private bool live; static void Main(string[] args) { CommandMap commands = new CommandMap(); commands.Add(new StopCommand()); commands.Add(new HelpCommand(commands)); + commands.Add(new ListEmbeddedResourcesCommand()); commands.Add(new GraphicalPlaygroundCommand()); - CommandProcessor processor = new CommandProcessor("The command \"{input}\" was not understood. Please type \"help\" for more information.", commands); + CommandProcessor processor = new CommandProcessor(commands); AssemblyName name = Assembly.GetExecutingAssembly().GetName(); - ConsoleInteraction consoleInteracter = new ConsoleInteraction("Tools"); - consoleInteracter.Tell(String.Format("{0} Version: {1}", name.Name, name.Version)); - consoleInteracter.Tell("Welcome to SlatedGameToolkit.Tools! These tools are meant for the developers using the SlatedGameToolkit. Type \"help\" for a list of things this tool can currently do."); - running = true; - while (running) { - consoleInteracter.Separate(); - processor.Process(consoleInteracter); + IInteractable interactable = (args.Length > 0 ? (IInteractable) new SingleConsoleInteraction(string.Join(' ', args)) : (IInteractable) new ConsoleInteraction("Tools")); + interactable.Tell(String.Format("{0} Version: {1}", name.Name, name.Version)); + if (args.Length > 0) { + interactable.Tell("Running in one time use mode."); + processor.Process(interactable); + } else { + interactable.Tell("Welcome to SlatedGameToolkit.Tools! These tools are meant for the developers using the SlatedGameToolkit. Type \"help\" for a list of things this tool can currently do."); + live = true; + while (live) { + interactable.Separate(); + processor.Process(interactable); + } } - consoleInteracter.Tell("Exiting tool."); + interactable.Tell("Exiting tool."); commands.Dispose(); } public static void Stop() { - running = false; + live = false; } } } diff --git a/src/SlatedGameToolkit.Tools/Resources/Playground/yhdnbgnc.png b/src/SlatedGameToolkit.Tools/Resources/Playground/yhdnbgnc.png new file mode 100644 index 0000000..ca73e80 Binary files /dev/null and b/src/SlatedGameToolkit.Tools/Resources/Playground/yhdnbgnc.png differ diff --git a/src/SlatedGameToolkit.Tools/SlatedGameToolkit.Tools.csproj b/src/SlatedGameToolkit.Tools/SlatedGameToolkit.Tools.csproj index 327b64e..9c07a29 100644 --- a/src/SlatedGameToolkit.Tools/SlatedGameToolkit.Tools.csproj +++ b/src/SlatedGameToolkit.Tools/SlatedGameToolkit.Tools.csproj @@ -11,4 +11,7 @@ A tool to help with developing a game using SlatedGameToolkit. + + + diff --git a/src/SlatedGameToolkit.Tools/Utilities/GraphicalPlayground/MainState.cs b/src/SlatedGameToolkit.Tools/Utilities/Playground/MainState.cs similarity index 50% rename from src/SlatedGameToolkit.Tools/Utilities/GraphicalPlayground/MainState.cs rename to src/SlatedGameToolkit.Tools/Utilities/Playground/MainState.cs index 94f7123..6b80852 100644 --- a/src/SlatedGameToolkit.Tools/Utilities/GraphicalPlayground/MainState.cs +++ b/src/SlatedGameToolkit.Tools/Utilities/Playground/MainState.cs @@ -1,18 +1,25 @@ using System; +using System.Drawing; +using System.Numerics; +using SlatedGameToolkit.Framework.Exceptions; using SlatedGameToolkit.Framework.Graphics.Programs; using SlatedGameToolkit.Framework.Graphics.Render; using SlatedGameToolkit.Framework.Graphics.Shaders; using SlatedGameToolkit.Framework.Graphics.Textures; using SlatedGameToolkit.Framework.Graphics.Window; +using SlatedGameToolkit.Framework.Loader; using SlatedGameToolkit.Framework.StateSystem; using SlatedGameToolkit.Framework.StateSystem.States; -namespace SlatedGameToolkit.Tools.Utilities.GraphicalPlayground +namespace SlatedGameToolkit.Tools.Utilities.Playground { public class MainState : IState { private WindowContext window; + private GLShaderProgram program; + private Camera2D camera; private Renderer renderer; + private Texture texture; private Sprite2D sprite; public WindowContext CurrentWindow { get { return window;}} @@ -30,6 +37,9 @@ namespace SlatedGameToolkit.Tools.Utilities.GraphicalPlayground public void Deinitialize() { window.Dispose(); + program.Dispose(); + texture.Dispose(); + renderer.Dispose(); } public string getName() @@ -37,14 +47,24 @@ namespace SlatedGameToolkit.Tools.Utilities.GraphicalPlayground return "main state"; } - public void Initialize(Manager manager) + public void Initialize(StateManager manager) { window = new WindowContext("SlatedGameToolkit Playground"); - renderer = new Renderer(); + camera = new Camera2D(); + camera.Width = window.WindowBoundaries.Width; + camera.Height = window.WindowBoundaries.Height; + camera.Position = new Vector2(camera.Width / 2, camera.Height / 2); + program = new GLShaderProgram(new NormalVertexShader(), new NormalFragmentShader()); + renderer = new Renderer(camera, program); + texture = new TextureLoader("Resources/Playground/yhdnbgnc.png").Load(); + sprite = new Sprite2D(texture, Color.White); } public void Render(double delta) { + OpenGLErrorException.CheckGLErrorStatus(); + renderer.Queue(sprite, Matrix4x4.Identity); + renderer.Render(); } public void Update(double delta)