diff --git a/src/SlatedGameToolkit.Framework/GameEngine.cs b/src/SlatedGameToolkit.Framework/GameEngine.cs index e0d1ba2..a7c564d 100644 --- a/src/SlatedGameToolkit.Framework/GameEngine.cs +++ b/src/SlatedGameToolkit.Framework/GameEngine.cs @@ -49,7 +49,7 @@ namespace SlatedGameToolkit.Framework { } private static void Loop(Object o) { - if (!(o is Manager)) throw new ArgumentException("The passed object needs to be of type manager."); + if (!(o is Manager)) throw new InternalFrameworkException(String.Format("Expected manager object for asynchronous loop. Got {0}", o)); Manager manager = (Manager) o; long currentTime = DateTimeOffset.Now.ToUnixTimeMilliseconds(); long timePassedFromLastUpdate = 0; @@ -113,6 +113,11 @@ namespace SlatedGameToolkit.Framework { lock (ignitionLock) { if (!loopCompleted) return false; loopCompleted = false; + + if (SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_MAJOR_VERSION, 3) < 0) throw new FrameworkSDLException(); + if (SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_MINOR_VERSION, 1) < 0) throw new FrameworkSDLException(); + if (SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_CONTEXT_PROFILE_MASK, SDL.SDL_GLprofile.SDL_GL_CONTEXT_PROFILE_CORE) < 0) throw new FrameworkSDLException(); + exit = false; if (SDL.SDL_Init(SDL.SDL_INIT_VIDEO) != 0) { throw new FrameworkSDLException(); diff --git a/src/SlatedGameToolkit.Framework/Graphics/Window/WindowHandle.cs b/src/SlatedGameToolkit.Framework/Graphics/Window/WindowHandle.cs index b37473a..56ec6f1 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Window/WindowHandle.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Window/WindowHandle.cs @@ -7,13 +7,39 @@ using SlatedGameToolkit.Framework.Exceptions; namespace SlatedGameToolkit.Framework.Graphics.Window { + /// + /// A delegate to determine the type of interaction with a window. + /// The method should be extremely lightweight as it can be called many times. + /// + /// The window coordinates that are being interacted with. + /// The region type. public delegate WindowRegion WindowRegionHit(FloatVector2 hitPoint); + + /// + /// A handle for a window. + /// This object itself is not thread safe. + /// public sealed class WindowHandle : IDisposable { + /// + /// The pointer referencing the SDL window. + /// public readonly IntPtr window; - public event WindowRegionHit windowRegionHitEvent; - IntPtr windowSurfaceHandle; + /// + /// The pointer referencing the OpenGL context. + /// + public readonly IntPtr glContext; + + /// + /// Event for when the window is being interacted with. + /// + public event WindowRegionHit windowRegionHitEvent; + + /// + /// Whether or not to show this window. + /// + /// True for showing. public bool Shown { set { if (value) { @@ -28,6 +54,10 @@ namespace SlatedGameToolkit.Framework.Graphics.Window } } + /// + /// The title displayed on the window. + /// + /// A string that represents whats to be displayed as the title of the window. public string WindowTitle { set { SDL.SDL_SetWindowTitle(window, value); @@ -38,6 +68,10 @@ namespace SlatedGameToolkit.Framework.Graphics.Window } } + /// + /// Whether or not to display the default window border. + /// + /// True if displaying borders. public bool WindowBordered { set { SDL.SDL_SetWindowBordered(window, value ? SDL.SDL_bool.SDL_TRUE : SDL.SDL_bool.SDL_FALSE); @@ -51,6 +85,10 @@ namespace SlatedGameToolkit.Framework.Graphics.Window } } + /// + /// Whether or not this window should be resizeable. + /// + /// True if resizeable. public bool WindowResizable { set { SDL.SDL_SetWindowResizable(window, value ? SDL.SDL_bool.SDL_TRUE : SDL.SDL_bool.SDL_FALSE); @@ -60,6 +98,11 @@ namespace SlatedGameToolkit.Framework.Graphics.Window } } + /// + /// The boundaries of the window represent both the bottom left corner relative to the screen, + /// as well as the current width and height of this window. + /// + /// Rectangle representing the boundaries of the window. public FloatRectangle WindowBoundaries { set { SDL.SDL_SetWindowPosition(window, (int)value.X1, (int)value.Y1); @@ -79,6 +122,10 @@ namespace SlatedGameToolkit.Framework.Graphics.Window } } + /// + /// The maximum size the window can be at any given time. + /// + /// A vector that represents the maximum width and height of the window with the x and y components respectively. public FloatVector2 MaximumSize { set { SDL.SDL_SetWindowMaximumSize(window, (int)value.x, (int)value.y); @@ -93,19 +140,10 @@ namespace SlatedGameToolkit.Framework.Graphics.Window } } - public float Opacity { - set { - int errorCode = SDL.SDL_SetWindowOpacity(window, value); - if (errorCode < 0) throw new OptionalSDLException(); - } - get { - float value; - int errorCode = SDL.SDL_GetWindowOpacity(window, out value); - if (errorCode < 0) throw new OptionalSDLException(); - return value; - } - } - + /// + /// The minimum size the window can be at any given time. + /// + /// A vector that represents the minimum width and height of the window with the x and y components respectively. public FloatVector2 MinimumSize { set { SDL.SDL_SetWindowMinimumSize(window, (int)value.x, (int)value.y); @@ -119,7 +157,29 @@ namespace SlatedGameToolkit.Framework.Graphics.Window return maxSize; } } + + /// + /// The opacity of the window itself. + /// This is not supported on all targetted platforms, and therefore, can throw an OptionalSDLException for when this is the case. + /// + /// A float with bounds of [0, 1] representing the opacity of the window. + public float Opacity { + set { + int errorCode = SDL.SDL_SetWindowOpacity(window, value); + if (errorCode < 0) throw new OptionalSDLException(); + } + get { + float value; + int errorCode = SDL.SDL_GetWindowOpacity(window, out value); + if (errorCode < 0) throw new OptionalSDLException(); + return value; + } + } + /// + /// Whether or not this window is grabbing the users input by making sure the mouse stays within this windows boundaries. + /// + /// True if grabbing. public bool GrabbingInput { set { SDL.SDL_SetWindowGrab(window, value ? SDL.SDL_bool.SDL_TRUE : SDL.SDL_bool.SDL_FALSE); @@ -134,10 +194,39 @@ namespace SlatedGameToolkit.Framework.Graphics.Window if (window == null) { throw new FrameworkSDLException(); } + glContext = SDL.SDL_GL_CreateContext(window); + if (glContext == null) { + throw new FrameworkSDLException(); + } if (SDL.SDL_SetWindowHitTest(window, SpecialRegionHit, IntPtr.Zero) < 0) { throw new OptionalSDLException(); } - windowSurfaceHandle = SDL.SDL_GetWindowSurface(window); + } + + /// + /// Makes this window the window that is currently being drawn to. + /// More specifically, it sets the OpenGL Context associated with this window to be the one + /// that is actively receiving all OpenGL calls. + /// + public void DrawToWindow() { + SDL.SDL_GL_MakeCurrent(window, glContext); + } + + /// + /// Raises this window to be above other windows. + /// + public void RaiseToTop() { + SDL.SDL_RaiseWindow(window); + } + + /// + /// Gets the index of the display that this window resides within. + /// + /// An integer representing the display this window resides within. + public int GetDisplayIndex() { + int index = SDL.SDL_GetWindowDisplayIndex(window); + if (index < 0) throw new FrameworkSDLException(); + return index; } private SDL.SDL_HitTestResult SpecialRegionHit(IntPtr window, IntPtr hitPtr, IntPtr data) { @@ -147,19 +236,12 @@ namespace SlatedGameToolkit.Framework.Graphics.Window return region.ToSDLHitTestResult(); } - public void RaiseToTop() { - SDL.SDL_RaiseWindow(window); - } - - public int GetDisplayIndex() { - int index = SDL.SDL_GetWindowDisplayIndex(window); - if (index < 0) throw new FrameworkSDLException(); - return index; - } - + /// + /// Disposes of this window and it's associated handles. + /// public void Dispose() { - SDL.SDL_FreeSurface(windowSurfaceHandle); + SDL.SDL_GL_DeleteContext(glContext); SDL.SDL_DestroyWindow(window); } diff --git a/src/SlatedGameToolkit.Framework/StateSystem/Manager.cs b/src/SlatedGameToolkit.Framework/StateSystem/Manager.cs index 31f72d4..29f38ff 100644 --- a/src/SlatedGameToolkit.Framework/StateSystem/Manager.cs +++ b/src/SlatedGameToolkit.Framework/StateSystem/Manager.cs @@ -1,14 +1,12 @@ using System; using System.Collections.Generic; using System.Threading; -using SlatedGameToolkit.Framework.Graphics.Window; using SlatedGameToolkit.Framework.StateSystem.States; namespace SlatedGameToolkit.Framework.StateSystem { public sealed class Manager : IDisposable { public Thread thread; - public readonly WindowHandle window; private IState currentState; private IState nextState; private Dictionary states; @@ -19,11 +17,9 @@ namespace SlatedGameToolkit.Framework.StateSystem /// None of the parameters can be null, and the initial state must exist in initial set of states. /// /// The name of the initial state. - /// The window handle being used for this set of states. /// The initial set of game states to be added. - public Manager(string initialState, WindowHandle window, params IState[] states) { + public Manager(string initialState, params IState[] states) { if (initialState == null) throw new ArgumentNullException("initialState"); - this.window = window ?? throw new ArgumentNullException("window"); this.states = new Dictionary(); thread = Thread.CurrentThread; addStates(states); @@ -117,12 +113,10 @@ namespace SlatedGameToolkit.Framework.StateSystem /// /// Disposes of this manager. - /// This also disposes the window and all the individual states. /// public void Dispose() { removeAllStates(); - window.Dispose(); } ~Manager() {