Work in progress new asset system.
This commit is contained in:
parent
d8eda24809
commit
8b2c26f9bb
@ -0,0 +1,26 @@
|
||||
using SlatedGameToolkit.Framework.AssetSystem;
|
||||
using SlatedGameToolkit.Framework.Graphics.OpenGL;
|
||||
using SlatedGameToolkit.Framework.Graphics.Textures;
|
||||
using SlatedGameToolkit.Framework.Graphics.Window;
|
||||
|
||||
namespace SlatedGameToolkit.Framework.AssetSystem.AssetData
|
||||
{
|
||||
public class TextureData : IAssetData
|
||||
{
|
||||
public readonly byte[] data;
|
||||
public readonly int width;
|
||||
public readonly int height;
|
||||
|
||||
public TextureData(int width, int height, byte[] data) {
|
||||
this.data = data;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public IAssetUseable InitializeUseable(GLContext glContext = null)
|
||||
{
|
||||
if (glContext == null) glContext = WindowContextsManager.CurrentGL;
|
||||
return new Texture(this, context: glContext);
|
||||
}
|
||||
}
|
||||
}
|
@ -14,23 +14,29 @@ namespace SlatedGameToolkit.Framework.AssetSystem {
|
||||
/// <param name="path">A path to modify.</param>
|
||||
/// <returns>The modified path.</returns>
|
||||
public delegate string ModifyPath(string path);
|
||||
|
||||
/// <summary>
|
||||
/// A delegate that performs the loading of the specific asset.
|
||||
/// </summary>
|
||||
/// <param name="path">The path of the asset.</param>
|
||||
/// <param name="glContext">The context to be used.</param>
|
||||
/// <param name="name">The path of the asset.</param>
|
||||
/// <typeparam name="T">The type of the resulting asset.</typeparam>
|
||||
/// <returns>A loaded, useable asset.</returns>
|
||||
public delegate T LoadAsset<T>(string path, GLContext glContext) where T : IAssetUseable;
|
||||
public delegate IAssetData LoadAsset(string path);
|
||||
|
||||
//TODO Implement change to two step asset pipeline.
|
||||
|
||||
public class AssetManager {
|
||||
public IAssetUseable this[string key] {
|
||||
get {
|
||||
if (!this.assets.ContainsKey(key)) { // if the data is still uninitialized, then do so.
|
||||
InitializeData(key);
|
||||
}
|
||||
return this.assets[key];
|
||||
}
|
||||
}
|
||||
private readonly object assetThreadLock = new object();
|
||||
private Thread thread;
|
||||
private ConcurrentQueue<(string, GLContext)> loadables;
|
||||
private ConcurrentQueue<string> loadables;
|
||||
private volatile bool load;
|
||||
public bool Complete {
|
||||
get {
|
||||
@ -57,12 +63,19 @@ namespace SlatedGameToolkit.Framework.AssetSystem {
|
||||
/// All file extensions will be requested in lower cases, and therefore, the extension key in this dictionary should also be all lowercase.
|
||||
/// </summary>
|
||||
/// <value>The dictionary that associates the loaders to their file extensions.</value>
|
||||
public ConcurrentDictionary<string, LoadAsset<IAssetUseable>> Loaders { get ; private set; }
|
||||
public AssetManager() {
|
||||
this.loadables = new ConcurrentQueue<(string, GLContext)>();
|
||||
public ConcurrentDictionary<string, LoadAsset> Loaders { get ; private set; }
|
||||
private ConcurrentDictionary<string, IAssetData> uninitializedDataDictionary;
|
||||
private ConcurrentBag<string> uninitializedDataBag;
|
||||
|
||||
private GLContext glContext;
|
||||
public AssetManager(GLContext glContext = null) {
|
||||
this.glContext = glContext ?? WindowContextsManager.CurrentGL;
|
||||
this.loadables = new ConcurrentQueue<string>();
|
||||
this.assets = new ConcurrentDictionary<string, IAssetUseable>();
|
||||
this.PathModifiers = new ConcurrentDictionary<string, ModifyPath>();
|
||||
this.Loaders = new ConcurrentDictionary<string, LoadAsset<IAssetUseable>>();
|
||||
this.Loaders = new ConcurrentDictionary<string, LoadAsset>();
|
||||
this.uninitializedDataDictionary = new ConcurrentDictionary<string, IAssetData>();
|
||||
this.uninitializedDataBag = new ConcurrentBag<string>();
|
||||
|
||||
thread = new Thread(Run);
|
||||
this.load = true;
|
||||
@ -77,20 +90,19 @@ namespace SlatedGameToolkit.Framework.AssetSystem {
|
||||
/// The file name of the loadable is the one the loadable is saved under.
|
||||
/// </summary>
|
||||
/// <param name="name">path of file.</param>
|
||||
public void QueueLoad(string name, GLContext glContext = null) {
|
||||
if (glContext == null) glContext = WindowContextsManager.CurrentGL;
|
||||
loadables.Enqueue((name, glContext));
|
||||
public void QueueLoad(string name) {
|
||||
loadables.Enqueue(name);
|
||||
}
|
||||
|
||||
private void Run() {
|
||||
while (load) {
|
||||
lock (assetThreadLock)
|
||||
{
|
||||
ValueTuple<string, GLContext> loadable;
|
||||
string loadable;
|
||||
while (loadables.TryDequeue(out loadable)) {
|
||||
Load(loadable.Item1, loadable.Item2);
|
||||
Load(loadable);
|
||||
}
|
||||
if (load) Monitor.Wait(assetThreadLock);
|
||||
if (load) Monitor.Wait(assetThreadLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,8 +111,7 @@ namespace SlatedGameToolkit.Framework.AssetSystem {
|
||||
/// Loads the loadable and stores it under the filename given to the loadable.
|
||||
/// </summary>
|
||||
/// <param name="name">The loadable to load.</param>
|
||||
/// <param name="glContext">The OpenGL context to associate with the loaded asset if the loaded asset requires it. May be null, in which the currently active context will be associated with it.</param>
|
||||
public void Load(string name, GLContext glContext = null) {
|
||||
public void Load(string name) {
|
||||
if (glContext == null) glContext = WindowContextsManager.CurrentGL;
|
||||
string original = name;
|
||||
string ext = Path.GetExtension(name).ToLower().Substring(1);
|
||||
@ -110,7 +121,24 @@ namespace SlatedGameToolkit.Framework.AssetSystem {
|
||||
name = DefaultPathModifier(name);
|
||||
}
|
||||
if (!Loaders.ContainsKey(ext)) throw new FrameworkUsageException(string.Format("Failed to find associated loader for file \"{0}\" with extension \"{1}\".", name, ext));
|
||||
assets[original] = Loaders[ext](name, glContext);
|
||||
uninitializedDataDictionary[original] = Loaders[ext](name);
|
||||
uninitializedDataBag.Add(name);
|
||||
GameEngine.ToRunQueue.Enqueue(InitializeDataRandom);
|
||||
}
|
||||
|
||||
private void InitializeDataRandom() {
|
||||
string name;
|
||||
if (uninitializedDataBag.TryTake(out name)) {
|
||||
if (this.uninitializedDataDictionary.ContainsKey(name)) {
|
||||
this.assets[name] = this.uninitializedDataDictionary[name].InitializeUseable(glContext);
|
||||
}
|
||||
} else {
|
||||
throw new InternalFrameworkException("Difference in queued uninitialized data loading quantity and actual quantity.");
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeData(string name) {
|
||||
this.assets[name] = this.uninitializedDataDictionary[name].InitializeUseable(glContext);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -122,6 +150,13 @@ namespace SlatedGameToolkit.Framework.AssetSystem {
|
||||
}
|
||||
}
|
||||
|
||||
public void WaitAndLoadAllQueued() {
|
||||
LoadQueued();
|
||||
Monitor.Enter(assetThreadLock);
|
||||
Monitor.Exit(assetThreadLock);
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unloads the asset under the given name.
|
||||
/// This disposes the asset as well as removes it from the manager.
|
||||
|
14
src/SlatedGameToolkit.Framework/AssetSystem/IAssetData.cs
Normal file
14
src/SlatedGameToolkit.Framework/AssetSystem/IAssetData.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using SlatedGameToolkit.Framework.Graphics.OpenGL;
|
||||
|
||||
namespace SlatedGameToolkit.Framework.AssetSystem
|
||||
{
|
||||
public interface IAssetData
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the asset data and returns the useable variant of said data.
|
||||
/// </summary>
|
||||
/// <param name="GLContext">The Open GL Context to use.</param>
|
||||
/// <returns>The associated useable asset.</returns>
|
||||
IAssetUseable InitializeUseable(GLContext GLContext);
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using SlatedGameToolkit.Framework.AssetSystem.AssetData;
|
||||
using SlatedGameToolkit.Framework.Graphics.OpenGL;
|
||||
using SlatedGameToolkit.Framework.Graphics.Textures;
|
||||
using StbImageSharp;
|
||||
@ -12,15 +13,14 @@ namespace SlatedGameToolkit.Framework.Loaders
|
||||
/// Any format supported by StbImage is therefore supported.
|
||||
/// </summary>
|
||||
/// <param name="path">The path of the texture to load.</param>
|
||||
/// <param name="glContext">The OpenGL context to associate the texture with.</param>
|
||||
/// <returns>A texture.</returns>
|
||||
public static Texture Load2DTexture(string path, GLContext glContext = null)
|
||||
/// <returns>The data for the texture.</returns>
|
||||
public static TextureData Load2DTexture(string path)
|
||||
{
|
||||
using (Stream stream = File.OpenRead(path))
|
||||
{
|
||||
ImageResult image = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha);
|
||||
TextureData textureData = new TextureData(image.Width, image.Height, image.Data);
|
||||
return new Texture(textureData, false, glContext);
|
||||
return textureData;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using SDL2;
|
||||
@ -23,6 +24,8 @@ namespace SlatedGameToolkit.Framework {
|
||||
private static volatile bool deltaChanged;
|
||||
private static TimeSpan updateDeltaTime = TimeSpan.FromSeconds(1d/40d), frameDeltaTime = TimeSpan.FromSeconds(1d/60d);
|
||||
|
||||
public static ConcurrentQueue<ThreadStart> ToRunQueue = new ConcurrentQueue<ThreadStart>();
|
||||
|
||||
/// <summary>
|
||||
/// The amount of updates per second.
|
||||
///
|
||||
@ -185,7 +188,13 @@ namespace SlatedGameToolkit.Framework {
|
||||
updateTimePassedFromLastRender = TimeSpan.Zero;
|
||||
timePassedFromLastRender = TimeSpan.Zero;
|
||||
} else {
|
||||
Thread.Yield();
|
||||
ThreadStart runnable;
|
||||
if (ToRunQueue.TryDequeue(out runnable)) {
|
||||
runnable();
|
||||
} else
|
||||
{
|
||||
Thread.Yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
stopped = true;
|
||||
|
@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using SlatedGameToolkit.Framework.AssetSystem;
|
||||
|
||||
namespace SlatedGameToolkit.Framework.Graphics.Textures
|
||||
{
|
||||
public interface ITexture : IDisposable
|
||||
public interface ITexture : IAssetUseable, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether or not this model uses a texture that is single chanelled.
|
||||
|
@ -3,6 +3,7 @@ using SlatedGameToolkit.Framework.Graphics.OpenGL;
|
||||
using SlatedGameToolkit.Framework.Graphics.Render;
|
||||
using SlatedGameToolkit.Framework.Graphics.Window;
|
||||
using SlatedGameToolkit.Framework.AssetSystem;
|
||||
using SlatedGameToolkit.Framework.AssetSystem.AssetData;
|
||||
|
||||
namespace SlatedGameToolkit.Framework.Graphics.Textures
|
||||
{
|
||||
|
@ -1,17 +0,0 @@
|
||||
using SlatedGameToolkit.Framework.AssetSystem;
|
||||
|
||||
namespace SlatedGameToolkit.Framework.Graphics.Textures
|
||||
{
|
||||
public class TextureData
|
||||
{
|
||||
public readonly byte[] data;
|
||||
public readonly int width;
|
||||
public readonly int height;
|
||||
|
||||
public TextureData(int width, int height, byte[] data) {
|
||||
this.data = data;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,13 +16,14 @@ namespace SlatedGameToolkit.Tools.CommandSystem
|
||||
/// The help should be a description of how to properly use this invokable.
|
||||
/// If an argument is specified, the help should cater to that specific argument.
|
||||
/// Information in the description does not need to be repeated.
|
||||
/// Arguments will always be lowercase or null.
|
||||
/// </summary>
|
||||
/// <param name="arg">An argument this invokable should describe. May be null, to which should return a string that describes this invokable in general.</param>
|
||||
/// <returns></returns>
|
||||
string getUsage(string arg);
|
||||
|
||||
/// <summary>
|
||||
/// Executes this invokable.
|
||||
/// Executes this invokable. Arguments will always be lowercase.
|
||||
/// </summary>
|
||||
/// <param name="interactable">The interactable object.</param>
|
||||
/// <param name="args">The arguments that followed the invokable.</param>
|
||||
|
33
src/SlatedGameToolkit.Tools/Commands/ExportCommand.cs
Normal file
33
src/SlatedGameToolkit.Tools/Commands/ExportCommand.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using SlatedGameToolkit.Tools.CommandSystem;
|
||||
using SlatedGameToolkit.Tools.CommandSystem.Interaction;
|
||||
|
||||
namespace SlatedGameToolkit.Tools.Commands
|
||||
{
|
||||
public class ExportCommand : IInvocable
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Execute(IInteractable interactable, string[] args)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public string getDescription()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public string[] GetInvokers()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public string getUsage(string arg)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -90,7 +90,25 @@ namespace SlatedGameToolkit.Tools.Commands
|
||||
|
||||
public string getUsage(string arg)
|
||||
{
|
||||
return "\"playground [start | stop | status | log | debug | framerate <framerate> | updates <update rate>]\"";
|
||||
if (arg == null) {
|
||||
return "\"playground [start | stop | status | log | debug | framerate <framerate> | updates <update rate>]\"";
|
||||
} else if (arg.Equals("start")) {
|
||||
return "Starts the playground.";
|
||||
} else if (arg.Equals("stop")) {
|
||||
return "Stops the playground.";
|
||||
} else if (arg.Equals("status")) {
|
||||
return "Retrieves the FPS, update rate, whether or not the playground is running, and if debugging is turned on.";
|
||||
} else if (arg.Equals("log")) {
|
||||
return "Toggles whether or not to attach logging to the console.";
|
||||
} else if (arg.Equals("debug")) {
|
||||
return "Toggles debugging. If logging is disabled, logging will be enabled.";
|
||||
} else if (arg.Equals("framerate")) {
|
||||
return "sets the FPS. Needs to be followed by a numerical value representing the new target FPS.";
|
||||
} else if (arg.Equals("updates")) {
|
||||
return "Sets the new update rate. Needs to be followed by a numerical value representing the target update rate.";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
@ -23,7 +23,14 @@ namespace SlatedGameToolkit.Tools.Commands
|
||||
builder.AppendJoin(", ", invocable.GetInvokers());
|
||||
interactable.Tell("Possible aliases: " + builder.ToString());
|
||||
interactable.Tell("Description: " + invocable.getDescription());
|
||||
interactable.Tell("Usage: " + invocable.getUsage(args.Length > 0 ? args[0] : null));
|
||||
if (args.Length > 1) {
|
||||
string desc = invocable.getUsage(args[1]);
|
||||
if (desc == null) {
|
||||
interactable.Tell(string.Format("Unable to find argument \"{0}\" for command \"{1}\". Please type \"help\" for more info.", args[1], args[0]));
|
||||
} else {
|
||||
interactable.Tell(args[1] + ": " + desc);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
interactable.Tell("--- Help ---");
|
||||
foreach (IInvocable invocable in commandMap)
|
||||
|
@ -10,6 +10,7 @@ using SlatedGameToolkit.Framework.Input.Devices;
|
||||
using SlatedGameToolkit.Framework.StateSystem;
|
||||
using SlatedGameToolkit.Framework.StateSystem.States;
|
||||
using SlatedGameToolkit.Framework.Graphics;
|
||||
using SlatedGameToolkit.Framework.AssetSystem;
|
||||
|
||||
namespace SlatedGameToolkit.Tools.Utilities.Playground
|
||||
{
|
||||
@ -19,7 +20,7 @@ namespace SlatedGameToolkit.Tools.Utilities.Playground
|
||||
private Camera2D camera;
|
||||
private MeshBatchRenderer renderer;
|
||||
private BitmapFont font;
|
||||
private Texture logoTexture, fillerTexture;
|
||||
private AssetManager assets;
|
||||
private RectangleMesh logo, textureTester, untextured;
|
||||
private string lastPressed;
|
||||
|
||||
@ -37,8 +38,7 @@ namespace SlatedGameToolkit.Tools.Utilities.Playground
|
||||
|
||||
public void Deinitialize()
|
||||
{
|
||||
logoTexture.Dispose();
|
||||
fillerTexture.Dispose();
|
||||
assets.UnloadAll();
|
||||
font.Dispose();
|
||||
renderer.Dispose();
|
||||
window.Dispose();
|
||||
@ -56,17 +56,21 @@ namespace SlatedGameToolkit.Tools.Utilities.Playground
|
||||
float ratio = drawableDimensions.Y / drawableDimensions.X;
|
||||
camera = new Camera2D(2f, ratio * 2f);
|
||||
renderer = new MeshBatchRenderer(camera, BatchVertexSize: 2048);
|
||||
assets = new AssetManager();
|
||||
assets.Loaders["png"] = TextureLoader.Load2DTexture;
|
||||
|
||||
logoTexture = TextureLoader.Load2DTexture("Resources/Playground/yhdnbgnc.png");
|
||||
logo = new RectangleMesh(logoTexture, Color.White);
|
||||
assets.QueueLoad("Resources/Playground/yhdnbgnc.png");
|
||||
assets.QueueLoad("Resources/Playground/filler.png");
|
||||
|
||||
assets.WaitAndLoadAllQueued();
|
||||
|
||||
logo = new RectangleMesh((ITexture)assets["Resources/Playground/yhdnbgnc.png"], Color.White);
|
||||
logo.Width = 0.5f;
|
||||
logo.Height = 0.5f;
|
||||
logo.X = -0.25f;
|
||||
logo.Y = -0.25f;
|
||||
|
||||
|
||||
fillerTexture = TextureLoader.Load2DTexture("Resources/Playground/filler.png");
|
||||
textureTester = new RectangleMesh(fillerTexture, Color.White);
|
||||
textureTester = new RectangleMesh((ITexture)assets["Resources/Playground/filler.png"], Color.White);
|
||||
textureTester.Width = 0.15f;
|
||||
textureTester.Height = 0.15f;
|
||||
textureTester.X = 0.25f;
|
||||
|
Loading…
Reference in New Issue
Block a user