145 lines
6.3 KiB
C#
145 lines
6.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Threading;
|
|
using SlatedGameToolkit.Framework.Graphics.Window;
|
|
using SlatedGameToolkit.Framework.StateSystem.States;
|
|
using SlatedGameToolkit.Framework.Utilities;
|
|
using SlatedGameToolkit.Framework.Graphics;
|
|
using SlatedGameToolkit.Framework.Graphics.OpenGL;
|
|
|
|
namespace SlatedGameToolkit.Framework.StateSystem
|
|
{
|
|
public sealed class StateManager : IDisposable {
|
|
public Thread thread;
|
|
public Color backgroundColour;
|
|
private IState currentState;
|
|
private IState nextState;
|
|
private Dictionary<string, IState> states;
|
|
|
|
/// <summary>
|
|
/// Instantiates a game state manager with an initial state, and a set of states to be added at the start.
|
|
/// States can later be added or removed.
|
|
/// None of the parameters can be null, and the initial state must exist in initial set of states.
|
|
/// </summary>
|
|
/// <param name="initialState">The name of the initial state.</param>
|
|
/// <param name="states">The initial set of game states to be added.</param>
|
|
internal StateManager() {
|
|
backgroundColour = Color.Orange;
|
|
|
|
this.states = new Dictionary<string, IState>();
|
|
}
|
|
|
|
internal void Initialize(IState initialState) {
|
|
if (initialState == null) throw new ArgumentNullException("initialState");
|
|
thread = Thread.CurrentThread;
|
|
currentState = initialState;
|
|
addState(initialState);
|
|
}
|
|
|
|
internal void update(double delta) {
|
|
if (nextState != null) {
|
|
if (currentState.Deactivate() & nextState.Activate()) {
|
|
currentState = nextState;
|
|
nextState = null;
|
|
}
|
|
}
|
|
currentState.Update(delta);
|
|
}
|
|
|
|
internal void render(double delta) {
|
|
WindowContext windowContext = WindowContextsManager.CurrentWindowContext;
|
|
windowContext.Context.ClearColor(backgroundColour.RedAsFloat(), backgroundColour.GreenAsFloat(), backgroundColour.BlueAsFloat(), 1f);
|
|
windowContext.Context.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
|
currentState.Render(delta);
|
|
windowContext.SwapBuffer();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Begins a state change. The current stage will be notified, and so will the state that is being changed to.
|
|
/// </summary>
|
|
/// <param name="name">The name of the state that we are turning to.</param>
|
|
public void changeState(string name) {
|
|
if (thread != Thread.CurrentThread) throw new ThreadStateException("State cannot be changed from a different thread.");
|
|
if (!states.TryGetValue(name, out nextState)) throw new ArgumentException("The requested state to change to does not exist in this manager.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds the given states to this manager under each of their own respective names.
|
|
/// Initializes all the states.
|
|
/// If there are two states of the same name, the first state in the array is added and the second is discarded.
|
|
/// The discarded state will not be initialized and dispose will not be called on it.
|
|
/// </summary>
|
|
/// <param name="states">The states to add.</param>
|
|
/// <returns>True if all the states were unique, and false if there were repetitions determined by name.</returns>
|
|
public bool addStates(IState[] states) {
|
|
if (states == null || states.Length == 0) throw new ArgumentException("The array of states cannot be null, and cannot be of size 0");
|
|
bool unique = true;
|
|
foreach (IState state in states)
|
|
{
|
|
unique = unique && addState(state);
|
|
}
|
|
return unique;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds the given state to this manager under it's own name.
|
|
/// Initializes the state as well.
|
|
/// Will not iniitialize the state if this method returns false.
|
|
/// </summary>
|
|
/// <param name="state">The state to be added to this manager.</param>
|
|
/// <returns>False if a state of this name has already been registered.</returns>
|
|
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);
|
|
} catch (ArgumentException) {
|
|
return false;
|
|
}
|
|
state.Initialize(this);
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the state given the name of the state.
|
|
/// If the state doesn't exist, nothing happens.
|
|
/// Will call dispose on the state.
|
|
/// </summary>
|
|
/// <param name="name">The name of the state.</param>
|
|
/// <returns>False if the state is being used, or the state doesn't exist.</returns>
|
|
public bool removeState(string name) {
|
|
if (thread != Thread.CurrentThread) throw new ThreadStateException("Cannot remove a state from a different thread.");
|
|
if (states[name] == currentState) return false;
|
|
IState state = states[name];
|
|
GameEngine.Logger.Debug("Removing state: " + name);
|
|
try {
|
|
state.Deinitialize();
|
|
} catch (Exception e) {
|
|
GameEngine.Logger.Error(e.ToString());
|
|
GameEngine.Logger.Error("Failed to deinitialize state: " + state.getName());
|
|
}
|
|
return states.Remove(name);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes all the states in this state manager except for the current one.
|
|
/// Disposes of the removed states.
|
|
/// </summary>
|
|
public void removeAllStates() {
|
|
GameEngine.Logger.Debug("Beginning to remove all states...");
|
|
foreach (String state in this.states.Keys)
|
|
{
|
|
removeState(state);
|
|
}
|
|
GameEngine.Logger.Debug("Completed removing all states...");
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (currentState == null) return;
|
|
currentState = null;
|
|
removeAllStates();
|
|
}
|
|
}
|
|
} |