Cleaned up asset loading system, and made progress on game engine structure.
This commit is contained in:
parent
8e2510903f
commit
635ed9fb7d
1
.vscode/launch.json
vendored
1
.vscode/launch.json
vendored
@ -4,6 +4,7 @@
|
||||
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
{
|
||||
"name": ".NET Core Launch (console)",
|
||||
"type": "coreclr",
|
||||
|
BIN
RecrownedGTK.Tests/assets/texture_test_2048x2048.png
Normal file
BIN
RecrownedGTK.Tests/assets/texture_test_2048x2048.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 675 KiB |
@ -9,11 +9,11 @@ namespace RecrownedGTK.AssetsSystem {
|
||||
public AssetLoader() {
|
||||
typeLoaders = new Dictionary<Type, ILoader>();
|
||||
}
|
||||
public void AddLoaderResolver(Type type, ILoader loader) {
|
||||
if (typeLoaders.ContainsKey(type)) {
|
||||
throw new InvalidOperationException(String.Format("The type {0} already exists in this resolver.", type));
|
||||
public void AddLoaderResolver(ILoader loader) {
|
||||
if (typeLoaders.ContainsKey(loader.resultingType)) {
|
||||
throw new InvalidOperationException(String.Format("The type {0} already exists in this resolver.", loader.resultingType));
|
||||
}
|
||||
typeLoaders.Add(type, loader);
|
||||
typeLoaders.Add(loader.resultingType, loader);
|
||||
}
|
||||
public void RemoveLoaderResolver(Type type) {
|
||||
if (!typeLoaders.ContainsKey(type)) {
|
||||
@ -21,6 +21,11 @@ namespace RecrownedGTK.AssetsSystem {
|
||||
}
|
||||
typeLoaders.Remove(type);
|
||||
}
|
||||
|
||||
public void RemoveLoaderResolver(ILoader loader) {
|
||||
RemoveLoaderResolver(loader.resultingType);
|
||||
}
|
||||
|
||||
public IInfo Load(string path, Type type) {
|
||||
if (!typeLoaders.ContainsKey(type)) {
|
||||
throw new InvalidOperationException(String.Format("The type {0} doesn't exist in this resolver.", type));
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
@ -11,16 +12,10 @@ namespace RecrownedGTK.AssetsSystem
|
||||
/// </summary>
|
||||
public class AssetManager
|
||||
{
|
||||
private AssetLoader assetLoader;
|
||||
readonly Queue<ContentData> queue;
|
||||
Dictionary<string, IDisposable> assets;
|
||||
/// <summary>
|
||||
/// Path modifiers to change the path in which the content manager looks to load a file. Used for better organizing things while not needing to type entire path.
|
||||
/// </summary>
|
||||
public readonly AssetLoader assetLoader;
|
||||
readonly Queue<AssetOutline> queue;
|
||||
ConcurrentDictionary<string, IDisposable> assets;
|
||||
private readonly Dictionary<Type, IAssetPathResolver> contentPathModifier;
|
||||
/// <summary>
|
||||
/// Used when no path modifier is defined for that specific type.
|
||||
/// </summary>
|
||||
public IAssetPathResolver normalPathModifier = new NormalAssetPathResolver();
|
||||
volatile float progress;
|
||||
volatile bool running;
|
||||
@ -36,13 +31,21 @@ namespace RecrownedGTK.AssetsSystem
|
||||
public float Progress { get { return progress; } }
|
||||
|
||||
/// <summary>
|
||||
/// Wraps the <see cref="ContentManager"/>.
|
||||
/// Creates an asset manager with a default asset loader.
|
||||
/// </summary>
|
||||
/// <param name="contentManager">The manager to wrap.</param>
|
||||
public AssetManager()
|
||||
public AssetManager() : this(new AssetLoader())
|
||||
{
|
||||
assets = new Dictionary<string, IDisposable>();
|
||||
queue = new Queue<ContentData>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A manager for the given asset loader.
|
||||
/// The manager will asynchronously load assets and store them.
|
||||
/// </summary>
|
||||
/// <param name="assetLoader">The asset loader to use for loading.</param>
|
||||
public AssetManager(AssetLoader assetLoader) {
|
||||
this.assetLoader = assetLoader;
|
||||
assets = new ConcurrentDictionary<string, IDisposable>();
|
||||
queue = new Queue<AssetOutline>();
|
||||
contentPathModifier = new Dictionary<Type, IAssetPathResolver>();
|
||||
}
|
||||
|
||||
@ -80,8 +83,7 @@ namespace RecrownedGTK.AssetsSystem
|
||||
}
|
||||
path = handler.Modify(assetName);
|
||||
}
|
||||
assets.Add(assetName, assetLoader.Load(path, type).CreateUseable());
|
||||
|
||||
assets.TryAdd(assetName, assetLoader.Load(path, type).CreateUseable());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -110,7 +112,7 @@ namespace RecrownedGTK.AssetsSystem
|
||||
{
|
||||
if (!assets.ContainsKey(assetName))
|
||||
{
|
||||
queue.Enqueue(new ContentData(assetName, typeof(T), usePathModifier));
|
||||
queue.Enqueue(new AssetOutline(assetName, typeof(T), usePathModifier));
|
||||
Debug.WriteLine("Queued asset: " + assetName);
|
||||
Update();
|
||||
}
|
||||
@ -145,7 +147,7 @@ namespace RecrownedGTK.AssetsSystem
|
||||
{
|
||||
lock (queue)
|
||||
{
|
||||
ContentData content = queue.Dequeue();
|
||||
AssetOutline content = queue.Dequeue();
|
||||
Load(content.assetName, content.type, content.usePathModifier);
|
||||
tasksCompleted++;
|
||||
progress = (float)tasksCompleted / totalTasks;
|
||||
@ -169,7 +171,8 @@ namespace RecrownedGTK.AssetsSystem
|
||||
{
|
||||
((IDisposable)assets[name]).Dispose();
|
||||
}
|
||||
assets.Remove(name);
|
||||
IDisposable disposable = null;
|
||||
assets.TryRemove(name, out disposable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -201,13 +204,13 @@ namespace RecrownedGTK.AssetsSystem
|
||||
Debug.WriteLine("Unloaded all assets.");
|
||||
}
|
||||
}
|
||||
private struct ContentData
|
||||
private struct AssetOutline
|
||||
{
|
||||
internal Type type;
|
||||
internal string assetName;
|
||||
internal bool usePathModifier;
|
||||
|
||||
public ContentData(string assetName, Type type, bool usePathModifier)
|
||||
public AssetOutline(string assetName, Type type, bool usePathModifier)
|
||||
{
|
||||
this.type = type;
|
||||
this.assetName = assetName;
|
||||
|
@ -1,9 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace RecrownedGTK.AssetsSystem.Information {
|
||||
/// <summary>
|
||||
/// Describes a serializable datatype.
|
||||
/// Meant for use as a part of the asset pipeline.
|
||||
/// </summary>
|
||||
public interface IInfo
|
||||
{
|
||||
Type type {get;}
|
||||
IDisposable CreateUseable();
|
||||
}
|
||||
}
|
12
RecrownedGTK/AssetsSystem/Information/IInformation.cs
Normal file
12
RecrownedGTK/AssetsSystem/Information/IInformation.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace RecrownedGTK.AssetsSystem.Information {
|
||||
/// <summary>
|
||||
/// An interface that describes an information class.
|
||||
/// An information class is class that can produce a useable asset object.
|
||||
/// In the asset pipeline, this is the second step, after loading the asset data.
|
||||
/// </summary>
|
||||
public interface IInformation
|
||||
{
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ namespace RecrownedGTK.AssetsSystem.Information {
|
||||
public struct TextureInfo : IInfo {
|
||||
public readonly byte[] textureData;
|
||||
int width, height;
|
||||
public Type type => typeof(TextureData);
|
||||
public Type resultingType => typeof(TextureData);
|
||||
public TextureInfo(int width, int height, byte[] textureData) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
@ -3,6 +3,7 @@ using RecrownedGTK.AssetsSystem.Information;
|
||||
namespace RecrownedGTK.AssetsSystem.Loaders {
|
||||
public interface ILoader
|
||||
{
|
||||
Type resultingType {get;}
|
||||
IInfo load(string path);
|
||||
}
|
||||
}
|
@ -7,6 +7,8 @@ using RecrownedGTK.Graphics;
|
||||
namespace RecrownedGTK.AssetsSystem.Loaders {
|
||||
public class TextureLoader : ILoader
|
||||
{
|
||||
public Type resultingType => typeof(TextureData);
|
||||
|
||||
public IInfo load(string path)
|
||||
{
|
||||
int width;
|
||||
|
@ -7,12 +7,8 @@ using RecrownedGTK.AssetsSystem;
|
||||
namespace RecrownedGTK.Game {
|
||||
public sealed class GameEngine : GameWindow {
|
||||
private IState state;
|
||||
public readonly Preferences preferences;
|
||||
public readonly AssetManager assets;
|
||||
public GameEngine(IState initialState, Preferences preferences, AssetManager assets) : base() {
|
||||
public GameEngine(IState initialState) : base() {
|
||||
this.state = initialState;
|
||||
this.assets = assets;
|
||||
this.preferences = preferences;
|
||||
}
|
||||
|
||||
protected override void OnUpdateFrame(FrameEventArgs e) {
|
||||
@ -34,7 +30,7 @@ namespace RecrownedGTK.Game {
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e) {
|
||||
if (state.CloseRequested()) {
|
||||
if (!state.CloseRequested()) {
|
||||
((CancelEventArgs) e).Cancel = true;
|
||||
}
|
||||
base.OnClosed(e);
|
||||
|
@ -3,13 +3,47 @@ using OpenTK.Input;
|
||||
namespace RecrownedGTK.Game {
|
||||
public interface IState
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when this state is going to be shown.
|
||||
/// </summary>
|
||||
/// <param name="gameManager">The instance of the game manager that is requesting this.</param>
|
||||
/// <returns>True of it's ready to be displayed, false otherwise.</returns>
|
||||
bool Shown(GameEngine gameManager);
|
||||
|
||||
/// <summary>
|
||||
/// Called on updating the state.
|
||||
/// </summary>
|
||||
/// <param name="time">The time that has passed since the last update in seconds.</param>
|
||||
void Update(double time);
|
||||
|
||||
/// <summary>
|
||||
/// Called for rendering things.
|
||||
/// </summary>
|
||||
/// <param name="time">The time that has elapsed since last rendering in seconds.</param>
|
||||
void Render(double time);
|
||||
|
||||
/// <summary>
|
||||
/// Called when this state is no longer being displayed.
|
||||
/// </summary>
|
||||
void Hidden();
|
||||
|
||||
/// <summary>
|
||||
/// Called when the game window size is updated.
|
||||
/// </summary>
|
||||
/// <param name="width">The new width</param>
|
||||
/// <param name="height">The new height</param>
|
||||
void WindowSizeUpdate(int width, int height);
|
||||
|
||||
/// <summary>
|
||||
/// When the game is being requested to be closed.
|
||||
/// </summary>
|
||||
/// <returns>True if closing is acceptable, or false otherwise.</returns>
|
||||
bool CloseRequested();
|
||||
|
||||
/// <summary>
|
||||
/// Called every update in the case that there should be a state change.
|
||||
/// </summary>
|
||||
/// <returns>Another state if ready to change states, or null if not.</returns>
|
||||
IState ChangeState();
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user