Began implementing an asset loading system.

This commit is contained in:
2020-06-03 01:36:24 -05:00
parent 484dbbece3
commit 23597f02b1
18 changed files with 288 additions and 118 deletions

View File

@@ -1,6 +1,6 @@
namespace SlatedGameToolkit.Framework.Graphics
{
internal enum GLEnums: uint {
public enum GLEnums: uint {
GL_DEPTH_BUFFER_BIT = 0x00000100,
GL_STENCIL_BUFFER_BIT = 0x00000400,
GL_COLOR_BUFFER_BIT = 0x00004000,

View File

@@ -6,99 +6,109 @@ using SlatedGameToolkit.Framework.Exceptions;
namespace SlatedGameToolkit.Framework.Graphics
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLClearColour(float r, float g, float b);
public delegate void GLClearColour(float r, float g, float b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLClear(GLEnums flags);
public delegate void GLClear(GLEnums flags);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLViewport(int x, int y, int width, int height);
public delegate void GLViewport(int x, int y, int width, int height);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate UIntPtr GLCreateShader(GLEnums type);
public delegate UIntPtr GLCreateShader(GLEnums type);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal 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)]
internal delegate void GLCompileShader(UIntPtr shaderHandle);
public delegate void GLCompileShader(UIntPtr shaderHandle);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLGetShaderLogInfo(UIntPtr shader, uint maxLength, out uint writtenLength, out string output);
public delegate void GLGetShaderLogInfo(UIntPtr shader, uint maxLength, out uint writtenLength, out string output);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate UIntPtr GLCreateProgram();
public delegate UIntPtr GLCreateProgram();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate UIntPtr GLDeleteProgram(UIntPtr program);
public delegate UIntPtr GLDeleteProgram(UIntPtr program);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLAttachShader(UIntPtr program, UIntPtr shader);
public delegate void GLAttachShader(UIntPtr program, UIntPtr shader);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLDetachShader(UIntPtr program, UIntPtr shader);
public delegate void GLDetachShader(UIntPtr program, UIntPtr shader);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLDeleteShader(UIntPtr shader);
public delegate void GLDeleteShader(UIntPtr shader);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLBindAttribLocation(UIntPtr program, uint index, string name);
public delegate void GLBindAttribLocation(UIntPtr program, uint index, string name);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLGetProgramInfoLog(UIntPtr program, uint maxLength, out uint writtenLength, out string output);
public delegate void GLGetProgramInfoLog(UIntPtr program, uint maxLength, out uint writtenLength, out string output);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLLinkProgram(UIntPtr program);
public delegate void GLLinkProgram(UIntPtr program);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLProgramParameter(UIntPtr program, GLEnums parameterName, int value);
public delegate void GLProgramParameter(UIntPtr program, GLEnums parameterName, int value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLUseProgram(UIntPtr program);
public delegate void GLUseProgram(UIntPtr program);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLGenProgramPipelines(uint size, UIntPtr[] pipelines);
public delegate void GLGenProgramPipelines(uint size, UIntPtr[] pipelines);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLDeleteProgramPipelines(uint size, UIntPtr[] pipelines);
public delegate void GLDeleteProgramPipelines(uint size, UIntPtr[] pipelines);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLBindProgramPipeline(UIntPtr pipeline);
public delegate void GLBindProgramPipeline(UIntPtr pipeline);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLUseProgramStages(UIntPtr pipeline, GLEnums bitField, UIntPtr program);
public delegate void GLUseProgramStages(UIntPtr pipeline, GLEnums bitField, UIntPtr program);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint GLGetError();
public delegate uint GLGetError();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate int GLGetAttribLocation(UIntPtr program, string attribName);
public delegate int GLGetAttribLocation(UIntPtr program, string attribName);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLBindBuffer(GLEnums target, UIntPtr buffer);
public delegate void GLBindBuffer(GLEnums target, UIntPtr buffer);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLGenBuffers(uint size, UIntPtr[] buffers);
public delegate void GLGenBuffers(uint size, UIntPtr[] buffers);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal unsafe delegate void GLBufferData(GLEnums target, uint size, Array data, GLEnums usage);
public unsafe delegate void GLBufferData(GLEnums target, uint size, Array data, GLEnums usage);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLDeleteBuffers(uint size, UIntPtr[] buffers);
public delegate void GLDeleteBuffers(uint size, UIntPtr[] buffers);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLVertexAttribPointer(uint index, int size, GLEnums type, bool normalized, uint stride, uint offset);
public delegate void GLVertexAttribPointer(uint index, int size, GLEnums type, bool normalized, uint stride, uint offset);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLGenVertexArrays(uint amount, UIntPtr[] arrays);
public delegate void GLGenVertexArrays(uint amount, UIntPtr[] arrays);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLDeleteVertexArrays(uint amount, UIntPtr[] arrays);
public delegate void GLDeleteVertexArrays(uint amount, UIntPtr[] arrays);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLBindVertexArray(UIntPtr array);
public delegate void GLBindVertexArray(UIntPtr array);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLEnableVertexAttribArray(uint attribIndex);
public delegate void GLEnableVertexAttribArray(uint attribIndex);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLDisableVertexAttribArray(uint attribIndex);
public delegate void GLDisableVertexAttribArray(uint attribIndex);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLDrawArrays(GLEnums mode, int first, uint count);
public delegate void GLDrawArrays(GLEnums mode, int first, uint count);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLDrawElements(GLEnums mode, uint count, int offset);
public delegate void GLDrawElements(GLEnums mode, uint count, int offset);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLMultiDrawArrays(GLEnums mode, int[] first, uint[] count, uint primout);
public delegate void GLMultiDrawArrays(GLEnums mode, int[] first, uint[] count, uint primout);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLMultiDrawElements(GLEnums mode, uint[] count, GLEnums type, IntPtr indices, int length);
public delegate void GLMultiDrawElements(GLEnums mode, uint[] count, GLEnums type, IntPtr indices, int length);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLGenTextures(uint n, UIntPtr[] textureHandles);
public delegate void GLGenTextures(uint n, UIntPtr[] textureHandles);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLBindTexture(GLEnums target, UIntPtr texture);
public delegate void GLBindTexture(GLEnums target, UIntPtr texture);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLDeleteTextures(uint n, UIntPtr[] textureHandles);
public delegate void GLDeleteTextures(uint n, UIntPtr[] textureHandles);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLTexParameteri(GLEnums target, GLEnums pname, int value);
public delegate void GLTexParameteri(GLEnums target, GLEnums pname, int value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLTexParameterf(GLEnums target, GLEnums pname, float value);
public delegate void GLTexParameterf(GLEnums target, GLEnums pname, float value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLTexParameteriv(GLEnums target, GLEnums pname, int[] values);
public delegate void GLTexParameteriv(GLEnums target, GLEnums pname, int[] values);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLTexParameterfv(GLEnums target, GLEnums pname, float[] values);
public delegate void GLTexParameterfv(GLEnums target, GLEnums pname, float[] values);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLTexImage2D(GLEnums target, int level, int internalFormat, uint width, uint height, int border, GLEnums format, GLEnums type, byte[] data);
public delegate void GLTexImage2D(GLEnums target, int level, int publicFormat, uint width, uint height, int border, GLEnums format, GLEnums type, byte[] data);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void GLGenerateMipMap(GLEnums target);
public delegate void GLGenerateMipMap(GLEnums target);
internal static class GLFunctionUtils {
public static class GLFunctionUtils {
/// <summary>
/// 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
/// lead to a CLR error on usage.
///
/// Uses SDL2 as the function address retriever.
/// </summary>
/// <param name="functionName">The process name, case sensitive, exactly as OpenGL defines it.</param>
/// <typeparam name="T">The delegate type to cast to.</typeparam>
/// <returns>The delegate associated with the retrieved path.</returns>
public static T RetrieveGLDelegate<T>(string functionName) where T : Delegate {
GameEngine.Logger.Debug(String.Format("Retrieving function with name: {0}", functionName));
IntPtr functionAddress = SDL.SDL_GL_GetProcAddress(functionName);

View File

@@ -6,16 +6,21 @@ using SlatedGameToolkit.Framework.Graphics.Window;
namespace SlatedGameToolkit.Framework.Graphics.Programs
{
/// <summary>
/// Represents a GL Program.
/// This class is abstract and serves as a parent to the possible types of programs.
/// Gives access to common OpenGL program associated function calls.
/// </summary>
public abstract class GLProgram : IDisposable
{
private WindowContext context;
private protected readonly UIntPtr handle;
private protected GLCreateProgram createProgram;
private protected GLDeleteProgram deleteProgram;
private protected GLLinkProgram linkProgram;
private protected GLGetProgramInfoLog getProgramInfoLog;
private protected GLProgramParameter programParameter;
private protected GLUseProgram useProgram;
protected readonly UIntPtr handle;
protected GLCreateProgram createProgram;
protected GLDeleteProgram deleteProgram;
protected GLLinkProgram linkProgram;
protected GLGetProgramInfoLog getProgramInfoLog;
protected GLProgramParameter programParameter;
private GLUseProgram useProgram;
/// <summary>
/// Creates an OpenGL program.

View File

@@ -18,6 +18,8 @@ namespace SlatedGameToolkit.Framework.Graphics.Programs
bindAttribLocation = GLFunctionUtils.RetrieveGLDelegate<GLBindAttribLocation>("glBindAttribLocation");
detachShader = GLFunctionUtils.RetrieveGLDelegate<GLDetachShader>("glDetachShader");
Use();
foreach (GLShader shader in shaders)
{
attachShader(handle, shader.Handle);

View File

@@ -2,6 +2,7 @@ using System;
using System.Runtime.InteropServices;
using SDL2;
using SlatedGameToolkit.Framework.Exceptions;
using SlatedGameToolkit.Framework.Graphics.Programs;
using SlatedGameToolkit.Framework.Graphics.Window;
namespace SlatedGameToolkit.Framework.Graphics.Shaders
@@ -10,14 +11,14 @@ namespace SlatedGameToolkit.Framework.Graphics.Shaders
private WindowContext context;
public UIntPtr Handle { get; private protected set; }
private protected GLCreateShader createShader;
private protected GLShaderSource shaderSource;
private protected GLCompileShader compileShader;
private protected GLGetShaderLogInfo getShaderLogInfo;
private protected GLGetAttribLocation getAttribLocation;
protected GLCreateShader createShader;
protected GLShaderSource shaderSource;
protected GLCompileShader compileShader;
protected GLGetShaderLogInfo getShaderLogInfo;
protected GLGetAttribLocation getAttribLocation;
private GLDeleteShader deleteShader;
internal GLShader() {
public GLShader() {
context = WindowContextsManager.CurrentWindowContext;
createShader = GLFunctionUtils.RetrieveGLDelegate<GLCreateShader>("glCreateShader");
shaderSource = GLFunctionUtils.RetrieveGLDelegate<GLShaderSource>("glShaderSource");

View File

@@ -4,7 +4,7 @@ using SlatedGameToolkit.Framework.Exceptions;
namespace SlatedGameToolkit.Framework.Graphics.Shaders
{
public class GLVertexArraySet : IDisposable {
public sealed class GLVertexArraySet : IDisposable {
private bool disposed;
public int Count { get; private set; }
private UIntPtr[] arrayBufferHandles;

View File

@@ -5,7 +5,7 @@ using SlatedGameToolkit.Framework.Graphics.Textures;
namespace SlatedGameToolkit.Framework.Graphics
{
public class GLTexture2DSet : IDisposable
public sealed class GLTexture2DSet : IDisposable
{
private bool disposed;
public int Count { get; private set; }
@@ -17,12 +17,8 @@ namespace SlatedGameToolkit.Framework.Graphics
private GLBindTexture bindTexture;
private GLGenerateMipMap generateMipMap;
private readonly UIntPtr[] handle;
private readonly bool linear, mipmap;
public GLTexture2DSet(TextureData[] textureDatas, bool linear = false, bool mipmap = false)
{
this.linear = linear;
this.mipmap = mipmap;
genTextures = GLFunctionUtils.RetrieveGLDelegate<GLGenTextures>("glGenTextures");
deleteTextures = GLFunctionUtils.RetrieveGLDelegate<GLDeleteTextures>("glDeleteTextures");
bindTexture = GLFunctionUtils.RetrieveGLDelegate<GLBindTexture>("glBindTexture");
@@ -42,15 +38,30 @@ namespace SlatedGameToolkit.Framework.Graphics
}
private void Setup(uint index, TextureData textureData) {
bindTexture(GLEnums.GL_TEXTURE_2D, handle[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_S, (int)GLEnums.GL_CLAMP_TO_EDGE);
texParameteri(GLEnums.GL_TEXTURE_2D, GLEnums.GL_TEXTURE_MIN_FILTER, (int)(linear ? (mipmap ? GLEnums.GL_LINEAR_MIPMAP_LINEAR : GLEnums.GL_LINEAR) : (mipmap ? GLEnums.GL_NEAREST_MIPMAP_LINEAR : GLEnums.GL_NEAREST)));
texParameteri(GLEnums.GL_TEXTURE_2D, GLEnums.GL_TEXTURE_MAG_FILTER, (int)(linear ? GLEnums.GL_LINEAR : GLEnums.GL_NEAREST));
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);
}
/// <summary>
/// Binds the given index's texture.
/// Sets the properties given the index of the OpenGL 2D texture.
/// </summary>
/// <param name="index">The index of the texture.</param>
/// <param name="linear">Whether or not to have linear filtering.</param>
/// <param name="mipmap">Whether or not to use MipMap</param>
public void SetProperties(uint index, GLEnums min, GLEnums 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);
}
/// <summary>
/// Binds a GL texture to the active unit.
/// </summary>
/// <param name="index">The index of the texture in this set.</param>
public void Bind(uint index) {
bindTexture(GLEnums.GL_TEXTURE_2D, handle[index]);

View File

@@ -1,8 +1,8 @@
using System;
using SlatedGameToolkit.Framework.Loader;
namespace SlatedGameToolkit.Framework.Graphics.Textures
{
public class Texture : IDisposable
public class Texture : IAssetUseable
{
private readonly GLTexture2DSet glTexture2DSet;
private readonly uint index;

View File

@@ -1,6 +1,8 @@
using SlatedGameToolkit.Framework.Loader;
namespace SlatedGameToolkit.Framework.Graphics.Textures
{
public struct TextureData
public class TextureData
{
public byte[] data;
public uint width;

View File

@@ -14,7 +14,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Window
/// </summary>
/// <param name="hitPoint">The window coordinates that are being interacted with.</param>
/// <returns>The region type.</returns>
public delegate WindowRegion WindowRegionHit(Vector2 hitPoint);
public delegate SDL.SDL_HitTestResult WindowRegionHit(Vector2 hitPoint);
/// <summary>
/// A delegate that represents a function to be called on a window resize.
@@ -260,9 +260,9 @@ namespace SlatedGameToolkit.Framework.Graphics.Window
/// <summary>
/// Instantiates a window handle.
/// </summary>
public WindowContext(string title, int x = -1, int y = -1, int width = 640, int height = 480, bool specialRegions = false, WindowOption options = default(WindowOption)) {
public WindowContext(string title, int x = -1, int y = -1, int width = 640, int height = 480, bool specialRegions = false, SDL.SDL_WindowFlags options = default(SDL.SDL_WindowFlags)) {
GameEngine.Logger.Information(String.Format("Starting openGL window with title \"{0}\"", title));
windowHandle = SDL.SDL_CreateWindow(title, x < 0 ? SDL.SDL_WINDOWPOS_CENTERED : x, y < 0 ? SDL.SDL_WINDOWPOS_CENTERED : y, width, height, SDL.SDL_WindowFlags.SDL_WINDOW_INPUT_FOCUS | SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL.SDL_WindowFlags.SDL_WINDOW_MOUSE_FOCUS | (SDL.SDL_WindowFlags) options);
windowHandle = SDL.SDL_CreateWindow(title, x < 0 ? SDL.SDL_WINDOWPOS_CENTERED : x, y < 0 ? SDL.SDL_WINDOWPOS_CENTERED : y, width, height, SDL.SDL_WindowFlags.SDL_WINDOW_INPUT_FOCUS | SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL.SDL_WindowFlags.SDL_WINDOW_MOUSE_FOCUS | options);
if (windowHandle == null) {
throw new FrameworkSDLException();
}
@@ -292,8 +292,8 @@ namespace SlatedGameToolkit.Framework.Graphics.Window
private SDL.SDL_HitTestResult SpecialRegionHit(IntPtr window, IntPtr hitPtr, IntPtr data) {
SDL.SDL_Point SDLPoint = Marshal.PtrToStructure<SDL.SDL_Point>(hitPtr);
Vector2 point = new Vector2(SDLPoint.x, SDLPoint.y);
WindowRegion region = windowRegionHitEvent.Invoke(point);
return (SDL.SDL_HitTestResult) region;
SDL.SDL_HitTestResult region = windowRegionHitEvent.Invoke(point);
return region;
}
internal void SwapBuffer() {

View File

@@ -1,19 +0,0 @@
using System;
using SDL2;
using SlatedGameToolkit.Framework.Exceptions;
namespace SlatedGameToolkit.Framework.Graphics.Window
{
public enum WindowRegion {
NORMAL = SDL.SDL_HitTestResult.SDL_HITTEST_NORMAL,
DRAGGABLE = SDL.SDL_HitTestResult.SDL_HITTEST_DRAGGABLE,
TOP_LEFT = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_TOPLEFT,
TOP_RIGHT = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_TOPRIGHT,
BOTTOM_LEFT = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_BOTTOMLEFT,
BOTTOM_RIGHT = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_BOTTOMRIGHT,
TOP = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_TOP,
BOTTOM = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_BOTTOM,
RIGHT = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_RIGHT,
LEFT = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_LEFT,
}
}

View File

@@ -1,11 +0,0 @@
using SDL2;
namespace SlatedGameToolkit.Framework.Graphics.Window
{
public enum WindowOption : uint
{
SHOWN = SDL.SDL_WindowFlags.SDL_WINDOW_SHOWN,
HIGH_DPI = SDL.SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI,
HIDDEN = SDL.SDL_WindowFlags.SDL_WINDOW_HIDDEN,
}
}

View File

@@ -0,0 +1,104 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
namespace SlatedGameToolkit.Framework.Loader {
public class AssetManager : IDisposable {
private readonly object assetThreadLock = new object();
private Thread thread;
private ConcurrentQueue<ILoadable> loadables;
private volatile bool load;
public bool Complete {
get {
return loadables.Count == 0;
}
}
private ConcurrentDictionary<string, IAssetUseable> assets;
public ConcurrentDictionary<Type, PathModifier> PathModifiers {get; private set; }
public AssetManager() {
this.loadables = new ConcurrentQueue<ILoadable>();
this.assets = new ConcurrentDictionary<string, IAssetUseable>();
this.PathModifiers = new ConcurrentDictionary<Type, PathModifier>();
thread = new Thread(Process);
this.load = true;
thread.Name = "Asset-Loader";
thread.IsBackground = true;
thread.Start();
}
/// <summary>
/// Queue's the loadable for batched loading.
/// The file name of the loadable is the one the loadable is saved under.
/// </summary>
/// <param name="loadable">The loadable.</param>
public void QueueLoad(ILoadable loadable) {
loadables.Enqueue(loadable);
}
private void Process() {
lock (assetThreadLock)
{
ILoadable loadable;
while (load) {
while (loadables.TryDequeue(out loadable)) {
Load(loadable);
}
Monitor.Pulse(loadable);
}
}
}
/// <summary>
/// Loads the loadable and stores it under the filename given to the loadable.
/// </summary>
/// <param name="loadable">The loadable to load.</param>
public void Load(ILoadable loadable) {
string name = loadable.FileName;
assets[name] = loadable.Load(PathModifiers[loadable.GetType()]);
}
/// <summary>
/// Loads the currently queued asynchronously.
/// </summary>
public void LoadQueued() {
if (Monitor.TryEnter(assetThreadLock)) {
Monitor.Pulse(assetThreadLock);
}
}
/// <summary>
/// Unloads the asset under the given name.
/// This disposes the asset as well as removes it from the manager.
/// </summary>
/// <param name="name">The name of the asset to unload.</param>
public void Unload(string name) {
IAssetUseable asset;
assets.TryRemove(name, out asset);
asset.Dispose();
}
/// <summary>
/// Removes all the assets.
/// </summary>
public void UnloadAll() {
foreach (string name in assets.Keys)
{
Unload(name);
}
}
/// <summary>
/// Disposes of all the stored assets.
/// </summary>
public void Dispose()
{
load = false;
UnloadAll();
}
~AssetManager() {
Dispose();
}
}
}

View File

@@ -0,0 +1,9 @@
using System;
namespace SlatedGameToolkit.Framework.Loader
{
public interface IAssetUseable : IDisposable
{
}
}

View File

@@ -0,0 +1,31 @@
namespace SlatedGameToolkit.Framework.Loader
{
/// <summary>
/// The method should modify the path.
/// </summary>
/// <param name="path">The path to modify.</param>
/// <returns>The modified path.</returns>
public delegate string PathModifier(string path);
/// <summary>
/// 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.
/// </summary>
public interface ILoadable
{
/// <summary>
/// The name of the file to load.
/// This is what the asset manager stores the results under.
/// </summary>
/// <value>A string representing the name to load.</value>
string FileName { get; }
/// <summary>
/// Loads the asset.
/// </summary>
/// <param name="pathModifier">Modifies the path. May be null. Default is null.</param>
/// <typeparam name="Useable">The loadable type.</typeparam>
/// <returns>The loadable type.</returns>
IAssetUseable Load(PathModifier pathModifier = null);
}
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Runtime.InteropServices;
using SDL2;
using SlatedGameToolkit.Framework.Exceptions;
using SlatedGameToolkit.Framework.Graphics.Textures;
using SlatedGameToolkit.Framework.Loader;
namespace SlatedGameToolkit.Framework.Loader
{
public class TextureLoader : ILoadable
{
public string FileName {get; private set; }
public TextureLoader(string path) {
this.FileName = path;
}
public IAssetUseable Load(PathModifier pathModifier = null)
{
IntPtr ptr = SDL_image.IMG_Load(pathModifier(FileName));
if (ptr == null) throw new FrameworkSDLException();
SDL.SDL_Surface surface = Marshal.PtrToStructure<SDL.SDL_Surface>(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);
return useable;
}
}
}

View File

@@ -1,8 +0,0 @@
namespace SlatedGameToolkit.Framework.Loaders
{
public interface ILoadable
{
bool RequiresLoading { get; }
void Load();
}
}