Make most subsystems available as protected properties in base Game class, implement IDisposable on systems.
This commit is contained in:
@@ -1,5 +1,3 @@
|
|||||||
using System.Numerics;
|
|
||||||
|
|
||||||
using Voile;
|
using Voile;
|
||||||
using Voile.Rendering;
|
using Voile.Rendering;
|
||||||
using Voile.Audio;
|
using Voile.Audio;
|
||||||
@@ -7,43 +5,16 @@ using Voile.Resources;
|
|||||||
using Voile.SceneGraph;
|
using Voile.SceneGraph;
|
||||||
using Voile.Utils;
|
using Voile.Utils;
|
||||||
|
|
||||||
|
|
||||||
public class TestGame : Game
|
public class TestGame : Game
|
||||||
{
|
{
|
||||||
public override string ResourceRoot => "Resources/";
|
public override string ResourceRoot => "Resources/";
|
||||||
|
|
||||||
public TestGame() : base()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
_renderer = new RaylibRenderer();
|
InitializeDefault();
|
||||||
|
|
||||||
_audioBackend = new FmodAudioBackend();
|
_audioBackend = new FmodAudioBackend();
|
||||||
_inputHandler = new RaylibInputHandler();
|
|
||||||
|
|
||||||
_renderer.CreateAndInitialize(new WindowSettings()
|
|
||||||
{
|
|
||||||
Title = "Test Game",
|
|
||||||
Size = new Vector2(1280, 720),
|
|
||||||
}, new RendererSettings()
|
|
||||||
{
|
|
||||||
UseVSync = true,
|
|
||||||
Fullscreen = false
|
|
||||||
});
|
|
||||||
|
|
||||||
_audioBackend.Initialize();
|
_audioBackend.Initialize();
|
||||||
|
|
||||||
_scene = new Scene(new SceneSettings()
|
|
||||||
{
|
|
||||||
Renderer = _renderer,
|
|
||||||
AudioBackend = _audioBackend,
|
|
||||||
InputHandler = _inputHandler,
|
|
||||||
ResourceManager = ResourceManager
|
|
||||||
});
|
|
||||||
|
|
||||||
_uiLayer = new UiLayer();
|
|
||||||
_worldLayer = new EntityLayer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadResources()
|
protected override void LoadResources()
|
||||||
@@ -66,9 +37,20 @@ public class TestGame : Game
|
|||||||
|
|
||||||
protected override void Ready()
|
protected override void Ready()
|
||||||
{
|
{
|
||||||
_inputHandler!.AddInputMapping("play", new InputAction[] { new KeyInputAction(KeyboardKey.Spacebar) });
|
_scene = new Scene(new SceneSettings()
|
||||||
_inputHandler.AddInputMapping("sprint", new InputAction[] { new KeyInputAction(KeyboardKey.LeftShift) });
|
{
|
||||||
_inputHandler.AddInputMapping("toggle_fullscreen", new InputAction[] { new KeyInputAction(KeyboardKey.F11) });
|
Renderer = Renderer,
|
||||||
|
AudioBackend = _audioBackend!,
|
||||||
|
InputHandler = Input,
|
||||||
|
ResourceManager = ResourceManager
|
||||||
|
});
|
||||||
|
|
||||||
|
_uiLayer = new UiLayer();
|
||||||
|
_worldLayer = new EntityLayer();
|
||||||
|
|
||||||
|
Input.AddInputMapping("play", new InputAction[] { new KeyInputAction(KeyboardKey.Spacebar) });
|
||||||
|
Input.AddInputMapping("sprint", new InputAction[] { new KeyInputAction(KeyboardKey.LeftShift) });
|
||||||
|
Input.AddInputMapping("toggle_fullscreen", new InputAction[] { new KeyInputAction(KeyboardKey.F11) });
|
||||||
|
|
||||||
_scene!.AddLayer("World", _worldLayer!);
|
_scene!.AddLayer("World", _worldLayer!);
|
||||||
|
|
||||||
@@ -91,15 +73,13 @@ public class TestGame : Game
|
|||||||
|
|
||||||
public override void Shutdown()
|
public override void Shutdown()
|
||||||
{
|
{
|
||||||
_renderer!.Shutdown();
|
ShutdownDefault();
|
||||||
_audioBackend?.Shutdown();
|
_audioBackend!.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Renderer? _renderer;
|
|
||||||
private Sound? _testSound;
|
private Sound? _testSound;
|
||||||
private Font? _font;
|
private Font? _font;
|
||||||
private FmodAudioBackend? _audioBackend;
|
private FmodAudioBackend? _audioBackend;
|
||||||
private InputHandler? _inputHandler;
|
|
||||||
private Scene? _scene;
|
private Scene? _scene;
|
||||||
|
|
||||||
private UiLayer? _uiLayer;
|
private UiLayer? _uiLayer;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace Voile.Audio
|
|||||||
{
|
{
|
||||||
public abstract void Initialize();
|
public abstract void Initialize();
|
||||||
public abstract void Update();
|
public abstract void Update();
|
||||||
public abstract void Shutdown();
|
protected abstract void Shutdown();
|
||||||
// BUS
|
// BUS
|
||||||
public abstract void CreateBus(string busName);
|
public abstract void CreateBus(string busName);
|
||||||
public abstract void SetBusVolume(string busName, float volume);
|
public abstract void SetBusVolume(string busName, float volume);
|
||||||
@@ -26,6 +26,7 @@ namespace Voile.Audio
|
|||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LehmerRandom _random = new LehmerRandom();
|
private LehmerRandom _random = new LehmerRandom();
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Voile.Audio
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
protected override void Shutdown()
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,11 @@ namespace Voile.Audio
|
|||||||
channelGroup.addDSP(0, dsp);
|
channelGroup.addDSP(0, dsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Shutdown()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private DSP CreateReverbDsp(AudioEffectReverb effectReverb)
|
private DSP CreateReverbDsp(AudioEffectReverb effectReverb)
|
||||||
{
|
{
|
||||||
DSP dsp;
|
DSP dsp;
|
||||||
@@ -122,11 +127,6 @@ namespace Voile.Audio
|
|||||||
return _channelGroups[busName];
|
return _channelGroups[busName];
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private FMOD.System _system;
|
private FMOD.System _system;
|
||||||
|
|
||||||
// TODO: use a different key for the dictionary, paths are not good :( (waste of memory lol)
|
// TODO: use a different key for the dictionary, paths are not good :( (waste of memory lol)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Voile.Rendering;
|
||||||
using Voile.Resources;
|
using Voile.Resources;
|
||||||
|
|
||||||
namespace Voile
|
namespace Voile
|
||||||
@@ -8,12 +9,36 @@ namespace Voile
|
|||||||
/// The ResourceManager associated with this game.
|
/// The ResourceManager associated with this game.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected ResourceManager ResourceManager { get; private set; }
|
protected ResourceManager ResourceManager { get; private set; }
|
||||||
public abstract string ResourceRoot { get; }
|
/// <summary>
|
||||||
|
/// The InputHandler associated with this game. Uses <see cref="RaylibInputHandler"/> by default.
|
||||||
|
/// </summary>
|
||||||
|
protected InputHandler Input { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Renderer associated with this game. Uses <see cref="RaylibRenderer"/> by default.
|
||||||
|
/// </summary>
|
||||||
|
protected Renderer Renderer { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resource root path for this game.
|
||||||
|
/// </summary>
|
||||||
|
public virtual string ResourceRoot => "Resources/";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Path to the engine configuration file.
|
||||||
|
/// </summary>
|
||||||
public virtual string EngineConfigPath => "engine.config";
|
public virtual string EngineConfigPath => "engine.config";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of this game. Also used as a default window title.
|
||||||
|
/// </summary>
|
||||||
|
public virtual string Name => "";
|
||||||
|
|
||||||
public Game()
|
public Game()
|
||||||
{
|
{
|
||||||
ResourceManager = new ResourceManager();
|
ResourceManager = new ResourceManager();
|
||||||
|
Input = new RaylibInputHandler();
|
||||||
|
Renderer = new RaylibRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -22,8 +47,6 @@ namespace Voile
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
Configure();
|
|
||||||
|
|
||||||
Initialize();
|
Initialize();
|
||||||
LoadResources();
|
LoadResources();
|
||||||
Ready();
|
Ready();
|
||||||
@@ -32,15 +55,36 @@ namespace Voile
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when it's time to initialize the subsystems.
|
/// Initializes subsystems using default types and settings.
|
||||||
|
/// </summary>
|
||||||
|
public void InitializeDefault()
|
||||||
|
{
|
||||||
|
ResourceManager.ResourceRoot = ResourceRoot;
|
||||||
|
|
||||||
|
Input = new RaylibInputHandler();
|
||||||
|
Renderer = new RaylibRenderer();
|
||||||
|
|
||||||
|
InitializeRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShutdownDefault()
|
||||||
|
{
|
||||||
|
Input.Dispose();
|
||||||
|
Renderer.Dispose();
|
||||||
|
ResourceManager.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when it's time to initialize the subsystems, or modify default game settings or systems.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract void Initialize();
|
public abstract void Initialize();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when it's time to load the application's resources, such as images or sounds.
|
/// Called when it's time to load the game's resources, such as images or sounds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected abstract void LoadResources();
|
protected abstract void LoadResources();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when it's safe to manipulate with the resources or/and systems.
|
/// Called when it's safe to manipulate with the resources or/and systems.
|
||||||
|
/// You can safely create game objects, scenes, etc. in this method.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected abstract void Ready();
|
protected abstract void Ready();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -52,9 +96,14 @@ namespace Voile
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract void Shutdown();
|
public abstract void Shutdown();
|
||||||
|
|
||||||
private void Configure()
|
private void InitializeRenderer()
|
||||||
{
|
{
|
||||||
ResourceManager.ResourceRoot = ResourceRoot;
|
var windowSettings = WindowSettings.Default;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(Name))
|
||||||
|
windowSettings.Title = Name;
|
||||||
|
|
||||||
|
Renderer.CreateAndInitialize(windowSettings, RendererSettings.Default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,14 +4,18 @@ using Voile.Utils;
|
|||||||
|
|
||||||
namespace Voile
|
namespace Voile
|
||||||
{
|
{
|
||||||
public abstract class InputHandler
|
public abstract class InputHandler : IDisposable
|
||||||
{
|
{
|
||||||
|
public static IReadOnlyDictionary<string, List<InputAction>> InputMappings => inputMappings;
|
||||||
|
|
||||||
public InputHandler()
|
public InputHandler()
|
||||||
{
|
{
|
||||||
inputMappings = new Dictionary<string, IEnumerable<InputAction>>();
|
inputMappings = new Dictionary<string, List<InputAction>>();
|
||||||
CreateDefaultMappings();
|
CreateDefaultMappings();
|
||||||
}
|
}
|
||||||
public Action OnInput;
|
|
||||||
|
public void Dispose() => GC.SuppressFinalize(this);
|
||||||
|
|
||||||
public bool Handled { get => _handled; set => _handled = value; }
|
public bool Handled { get => _handled; set => _handled = value; }
|
||||||
public abstract bool IsKeyboardKeyDown(KeyboardKey key);
|
public abstract bool IsKeyboardKeyDown(KeyboardKey key);
|
||||||
public abstract bool KeyboardKeyJustPressed(KeyboardKey key);
|
public abstract bool KeyboardKeyJustPressed(KeyboardKey key);
|
||||||
@@ -36,7 +40,7 @@ namespace Voile
|
|||||||
|
|
||||||
public void AddInputMapping(string actionName, IEnumerable<InputAction> inputActions)
|
public void AddInputMapping(string actionName, IEnumerable<InputAction> inputActions)
|
||||||
{
|
{
|
||||||
inputMappings.Add(actionName, inputActions);
|
inputMappings.Add(actionName, inputActions.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateDefaultMappings()
|
private void CreateDefaultMappings()
|
||||||
@@ -75,9 +79,9 @@ namespace Voile
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _handled;
|
|
||||||
protected Dictionary<string, IEnumerable<InputAction>> inputMappings;
|
|
||||||
|
|
||||||
|
protected static Dictionary<string, List<InputAction>> inputMappings = new();
|
||||||
|
private bool _handled;
|
||||||
private Logger _logger = new(nameof(InputHandler));
|
private Logger _logger = new(nameof(InputHandler));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,6 @@ namespace Voile
|
|||||||
public override bool IsKeyboardKeyDown(KeyboardKey key)
|
public override bool IsKeyboardKeyDown(KeyboardKey key)
|
||||||
{
|
{
|
||||||
Raylib_cs.KeyboardKey rayKey = (Raylib_cs.KeyboardKey)key;
|
Raylib_cs.KeyboardKey rayKey = (Raylib_cs.KeyboardKey)key;
|
||||||
OnInput?.Invoke();
|
|
||||||
return Raylib.IsKeyDown(rayKey);
|
return Raylib.IsKeyDown(rayKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace Voile.Rendering
|
|||||||
return Raylib.WindowShouldClose();
|
return Raylib.WindowShouldClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Shutdown()
|
protected override void Shutdown()
|
||||||
{
|
{
|
||||||
Raylib.CloseWindow();
|
Raylib.CloseWindow();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Voile.Rendering
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// An abstract class representing the graphics renderer.
|
/// An abstract class representing the graphics renderer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class Renderer
|
public abstract class Renderer : IDisposable
|
||||||
{
|
{
|
||||||
// INIT
|
// INIT
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -46,6 +46,13 @@ namespace Voile.Rendering
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract Vector2 MonitorSize { get; }
|
public abstract Vector2 MonitorSize { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Shutdown();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a window.
|
/// Creates a window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -59,7 +66,7 @@ namespace Voile.Rendering
|
|||||||
protected abstract int GetMonitorHeight(int monitorId);
|
protected abstract int GetMonitorHeight(int monitorId);
|
||||||
protected abstract int GetCurrentMonitor();
|
protected abstract int GetCurrentMonitor();
|
||||||
protected abstract bool WindowShouldClose();
|
protected abstract bool WindowShouldClose();
|
||||||
public abstract void Shutdown();
|
protected abstract void Shutdown();
|
||||||
|
|
||||||
// DRAWING
|
// DRAWING
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -171,7 +178,7 @@ namespace Voile.Rendering
|
|||||||
public struct WindowSettings
|
public struct WindowSettings
|
||||||
{
|
{
|
||||||
public string Title;
|
public string Title;
|
||||||
public Vector2 Size = new Vector2(640, 480);
|
public Vector2 Size = new Vector2(1280, 720);
|
||||||
public bool Resizable { get; set; }
|
public bool Resizable { get; set; }
|
||||||
|
|
||||||
public WindowSettings(string title, Vector2 size)
|
public WindowSettings(string title, Vector2 size)
|
||||||
@@ -179,5 +186,7 @@ namespace Voile.Rendering
|
|||||||
Title = title;
|
Title = title;
|
||||||
Size = size;
|
Size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static WindowSettings Default => new("Voile Game", new Vector2(1280, 720));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,7 @@ namespace Voile.Rendering
|
|||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Shutdown()
|
protected override void Shutdown()
|
||||||
{
|
{
|
||||||
_window!.DoEvents();
|
_window!.DoEvents();
|
||||||
_window.Reset();
|
_window.Reset();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Voile.Utils;
|
|||||||
|
|
||||||
namespace Voile.Resources
|
namespace Voile.Resources
|
||||||
{
|
{
|
||||||
public class ResourceManager
|
public class ResourceManager : IDisposable
|
||||||
{
|
{
|
||||||
public string ResourceRoot { get; set; } = "Resources/";
|
public string ResourceRoot { get; set; } = "Resources/";
|
||||||
|
|
||||||
@@ -49,6 +49,24 @@ namespace Voile.Resources
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryUnload(string resourceId)
|
||||||
|
{
|
||||||
|
_logger.Info($"Unloading resource with id \"{resourceId}\"...");
|
||||||
|
|
||||||
|
if (!_loadedResources.ContainsKey(resourceId))
|
||||||
|
{
|
||||||
|
_logger.Error($"Cannot unload resource with id \"{resourceId}\": resource doesn't exist!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resource = _loadedResources[resourceId];
|
||||||
|
|
||||||
|
_loadedResources.Remove(resourceId);
|
||||||
|
resource.Dispose();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public bool TrySave<T>(string path, in T resource) where T : Resource
|
public bool TrySave<T>(string path, in T resource) where T : Resource
|
||||||
{
|
{
|
||||||
if (!TryGetSaver(out IResourceSaver<T>? saver))
|
if (!TryGetSaver(out IResourceSaver<T>? saver))
|
||||||
@@ -151,6 +169,17 @@ namespace Voile.Resources
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
foreach (var resource in _loadedResources)
|
||||||
|
{
|
||||||
|
TryUnload(resource.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Logger _logger = new(nameof(ResourceManager));
|
private Logger _logger = new(nameof(ResourceManager));
|
||||||
|
|
||||||
private readonly Dictionary<Type, object> _resourceLoaderAssociations = new()
|
private readonly Dictionary<Type, object> _resourceLoaderAssociations = new()
|
||||||
|
|||||||
Reference in New Issue
Block a user