Added window control grabbing and special hit testing.

Also cleaned up and added exceptions to better structure exception handling.

Many small changes to improve useability of framework.

Some refactoring.
This commit is contained in:
Harrison Deng 2020-05-23 22:48:55 -05:00
parent bd6b085687
commit 7a6f709e9a
12 changed files with 168 additions and 28 deletions

View File

@ -2,5 +2,10 @@ namespace SlatedGameToolkit.Framework.DataTypes
{
public struct FloatVector2 {
public volatile float x, y;
public FloatVector2(float x, float y) {
this.x = x;
this.y = y;
}
}
}

View File

@ -0,0 +1,17 @@
using System;
namespace SlatedGameToolkit.Framework.Exceptions
{
public abstract class FrameworkException : Exception {
public FrameworkException() {
}
public FrameworkException(string message) : base(message) {
}
public FrameworkException(string message, Exception inner) : base(message, inner) {
}
}
}

View File

@ -0,0 +1,21 @@
using System;
namespace SlatedGameToolkit.Framework.Exceptions
{
/// <summary>
/// Any errors generated by an SDL feature that the engine requires are wrapped in the form of this type of exception.
/// </summary>
public class FrameworkSDLException : SDLException {
public FrameworkSDLException() : base() {
}
public FrameworkSDLException(string message) : base(message) {
}
public FrameworkSDLException(string message, Exception inner) : base(message, inner) {
}
}
}

View File

@ -0,0 +1,20 @@
using System;
namespace SlatedGameToolkit.Framework.Exceptions
{
/// <summary>
/// An exception that is thrown when there is an inappropriate use of the framework.
/// </summary>
public class FrameworkUsageException : FrameworkException {
public FrameworkUsageException() : base() {
}
public FrameworkUsageException(string message) : base(message) {
}
public FrameworkUsageException(string message, Exception inner) : base(message, inner) {
}
}
}

View File

@ -0,0 +1,18 @@
using System;
namespace SlatedGameToolkit.Framework.Exceptions
{
internal class InternalFrameworkException : FrameworkException {
const string ADDITIONAL_MESSAGE = "\nThis exception is a framework bug!";
public InternalFrameworkException() : base() {
}
public InternalFrameworkException(string message) : base(message + ADDITIONAL_MESSAGE) {
}
public InternalFrameworkException(string message, Exception inner) : base(message + ADDITIONAL_MESSAGE, inner) {
}
}
}

View File

@ -0,0 +1,22 @@
using System;
namespace SlatedGameToolkit.Framework.Exceptions
{
/// <summary>
/// This exception is produced when the error producing SDL feature is not something the framework considers critical.
/// This can happen if not all framework supported platforms support a specific feature that SDL provides.
/// </summary>
public class OptionalSDLException : SDLException {
public OptionalSDLException() : base() {
}
public OptionalSDLException(string message) : base(message) {
}
public OptionalSDLException(string message, Exception inner) : base(message, inner) {
}
}
}

View File

@ -7,7 +7,7 @@ namespace SlatedGameToolkit.Framework.Exceptions
/// An SDLException is defined as an exception that is thrown whenever an error occurrs in any SDL functions.
/// </summary>
[Serializable]
public class SDLException : Exception {
public abstract class SDLException : Exception {
public string SDLMessage { get; }
/// <summary>

View File

@ -1,17 +0,0 @@
using System;
namespace SlatedGameToolkit.Framework.Exceptions
{
public class SlatedGameToolkitException : Exception {
public SlatedGameToolkitException() {
}
public SlatedGameToolkitException(string message) : base(message) {
}
public SlatedGameToolkitException(string message, Exception inner) : base(message, inner) {
}
}
}

View File

@ -5,7 +5,6 @@ using Serilog;
using Serilog.Core;
using SlatedGameToolkit.Framework.Exceptions;
using SlatedGameToolkit.Framework.StateSystem;
using SlatedGameToolkit.Framework.Window;
namespace SlatedGameToolkit.Framework {
/// <summary>
@ -108,7 +107,7 @@ namespace SlatedGameToolkit.Framework {
logger.Warning(String.Format("Engine was designed with SDL version {0}, currently running on {1}", SDLVersion.ToString(), SDLBuiltVersion.ToString()));
if (SDLVersion.major < 2) {
logger.Error("This engine was designed to work with SDL2. The version you're currently running is severely outdated.");
throw new SlatedGameToolkitException("Outdated SDL binaries.");
throw new FrameworkUsageException("Outdated SDL binaries.");
}
}
lock (ignitionLock) {
@ -116,10 +115,10 @@ namespace SlatedGameToolkit.Framework {
loopCompleted = false;
exit = false;
if (SDL.SDL_Init(SDL.SDL_INIT_VIDEO) != 0) {
throw new SDLException();
throw new FrameworkSDLException();
}
if (SDL.SDL_Init(SDL.SDL_INIT_AUDIO) != 0) {
throw new SDLException();
throw new FrameworkSDLException();
}
thread = new Thread(Loop);
thread.Start(manager);

View File

@ -1,13 +1,17 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using SDL2;
using SlatedGameToolkit.Framework.DataTypes;
using SlatedGameToolkit.Framework.Exceptions;
namespace SlatedGameToolkit.Framework.Graphics.Window
{
public delegate WindowRegion WindowRegionHit(FloatVector2 hitPoint);
public sealed class WindowHandle : IDisposable
{
public readonly IntPtr window;
public event WindowRegionHit windowRegionHitEvent;
IntPtr windowSurfaceHandle;
public bool Shown {
@ -42,7 +46,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Window
get {
int top, bottom, left, right;
int errorCode = SDL.SDL_GetWindowBordersSize(window, out top, out left, out bottom, out right);
if (errorCode < 0) throw new SDLException();
if (errorCode < 0) throw new OptionalSDLException();
return top > 0 || bottom > 0 || left > 0 || right > 0;
}
}
@ -92,12 +96,12 @@ namespace SlatedGameToolkit.Framework.Graphics.Window
public float Opacity {
set {
int errorCode = SDL.SDL_SetWindowOpacity(window, value);
if (errorCode < 0) throw new SDLException();
if (errorCode < 0) throw new OptionalSDLException();
}
get {
float value;
int errorCode = SDL.SDL_GetWindowOpacity(window, out value);
if (errorCode < 0) throw new SDLException();
if (errorCode < 0) throw new OptionalSDLException();
return value;
}
}
@ -116,18 +120,40 @@ namespace SlatedGameToolkit.Framework.Graphics.Window
}
}
public WindowHandle(string title, int x, int y, int width, int height, WindowOptions options) {
public bool GrabbingInput {
set {
SDL.SDL_SetWindowGrab(window, value ? SDL.SDL_bool.SDL_TRUE : SDL.SDL_bool.SDL_FALSE);
}
get {
return SDL.SDL_GetWindowGrab(window) == SDL.SDL_bool.SDL_TRUE ? true : false;
}
}
public WindowHandle(string title, int x, int y, int width, int height, bool specialRegions, WindowOptions options) {
window = SDL.SDL_CreateWindow(title, x, y, width, height, SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL | options.ToSDLWindowFlag());
if (window == null) {
throw new FrameworkSDLException();
}
if (SDL.SDL_SetWindowHitTest(window, SpecialRegionHit, IntPtr.Zero) < 0) {
throw new OptionalSDLException();
}
windowSurfaceHandle = SDL.SDL_GetWindowSurface(window);
}
private SDL.SDL_HitTestResult SpecialRegionHit(IntPtr window, IntPtr hitPtr, IntPtr data) {
SDL.SDL_Point SDLPoint = Marshal.PtrToStructure<SDL.SDL_Point>(hitPtr);
FloatVector2 point = new FloatVector2(SDLPoint.x, SDLPoint.y);
WindowRegion region = windowRegionHitEvent.Invoke(point);
return region.ToSDLHitTestResult();
}
public void RaiseToTop() {
SDL.SDL_RaiseWindow(window);
}
public int GetDisplayIndex() {
int index = SDL.SDL_GetWindowDisplayIndex(window);
if (index < 0) throw new SDLException();
if (index < 0) throw new FrameworkSDLException();
return index;
}

View File

@ -0,0 +1,28 @@
using System;
using SDL2;
using SlatedGameToolkit.Framework.Exceptions;
namespace SlatedGameToolkit.Framework.Graphics.Window
{
public enum WindowRegion {
NORMAL = SDL.SDL_HitTestResult.SDL_HITTEST_NORMAL,
DRAGGABLE = SDL.SDL_HitTestResult.SDL_HITTEST_DRAGGABLE,
TOP_LEFT = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_TOPLEFT,
TOP_RIGHT = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_TOPRIGHT,
BOTTOM_LEFT = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_BOTTOMLEFT,
BOTTOM_RIGHT = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_BOTTOMRIGHT,
TOP = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_TOP,
BOTTOM = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_BOTTOM,
RIGHT = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_RIGHT,
LEFT = SDL.SDL_HitTestResult.SDL_HITTEST_RESIZE_LEFT,
}
internal static class WindowRegionExtensions {
public static SDL.SDL_HitTestResult ToSDLHitTestResult(this WindowRegion region) {
SDL.SDL_HitTestResult result;
if (!Enum.TryParse(((int) region).ToString(), out result)) throw new InternalFrameworkException("Unable to convert window regions.");
return result;
}
}
}

View File

@ -1,5 +1,6 @@
using System;
using SDL2;
using SlatedGameToolkit.Framework.Exceptions;
namespace SlatedGameToolkit.Framework.Graphics.Window
{
@ -11,7 +12,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Window
internal static class WindowOptionsExtension {
public static SDL.SDL_WindowFlags ToSDLWindowFlag(this WindowOptions options) {
SDL.SDL_WindowFlags sdlFlag;
Enum.TryParse(((uint) options).ToString(), out sdlFlag);
if (!(Enum.TryParse(((uint) options).ToString(), out sdlFlag))) throw new InternalFrameworkException("Unable to convert window options.");
return sdlFlag;
}
}