diff --git a/Framework/App.cs b/Framework/App.cs
index fa428e4..66e50b8 100644
--- a/Framework/App.cs
+++ b/Framework/App.cs
@@ -14,9 +14,9 @@ public static class App
private static TimeSpan accumulator;
private static string title = string.Empty;
private static Platform.FosterFlags flags =
- Platform.FosterFlags.RESIZABLE |
- Platform.FosterFlags.VSYNC |
- Platform.FosterFlags.MOUSE_VISIBLE;
+ Platform.FosterFlags.Resizable |
+ Platform.FosterFlags.Vsync |
+ Platform.FosterFlags.MouseVisible;
///
/// Foster Version Number
@@ -183,11 +183,11 @@ public static Point2 SizeInPixels
///
public static bool Fullscreen
{
- get => flags.Has(Platform.FosterFlags.FULLSCREEN);
+ get => flags.Has(Platform.FosterFlags.Fullscreen);
set
{
- if (value) flags |= Platform.FosterFlags.FULLSCREEN;
- else flags &= ~Platform.FosterFlags.FULLSCREEN;
+ if (value) flags |= Platform.FosterFlags.Fullscreen;
+ else flags &= ~Platform.FosterFlags.Fullscreen;
Platform.FosterSetFlags(flags);
}
}
@@ -197,11 +197,11 @@ public static bool Fullscreen
///
public static bool Resizable
{
- get => flags.Has(Platform.FosterFlags.RESIZABLE);
+ get => flags.Has(Platform.FosterFlags.Resizable);
set
{
- if (value) flags |= Platform.FosterFlags.RESIZABLE;
- else flags &= ~Platform.FosterFlags.RESIZABLE;
+ if (value) flags |= Platform.FosterFlags.Resizable;
+ else flags &= ~Platform.FosterFlags.Resizable;
Platform.FosterSetFlags(flags);
}
}
@@ -211,11 +211,11 @@ public static bool Resizable
///
public static bool VSync
{
- get => flags.Has(Platform.FosterFlags.VSYNC);
+ get => flags.Has(Platform.FosterFlags.Vsync);
set
{
- if (value) flags |= Platform.FosterFlags.VSYNC;
- else flags &= ~Platform.FosterFlags.VSYNC;
+ if (value) flags |= Platform.FosterFlags.Vsync;
+ else flags &= ~Platform.FosterFlags.Vsync;
Platform.FosterSetFlags(flags);
}
}
@@ -225,11 +225,11 @@ public static bool VSync
///
public static bool MouseVisible
{
- get => flags.Has(Platform.FosterFlags.MOUSE_VISIBLE);
+ get => flags.Has(Platform.FosterFlags.MouseVisible);
set
{
- if (value) flags |= Platform.FosterFlags.MOUSE_VISIBLE;
- else flags &= ~Platform.FosterFlags.MOUSE_VISIBLE;
+ if (value) flags |= Platform.FosterFlags.MouseVisible;
+ else flags &= ~Platform.FosterFlags.MouseVisible;
Platform.FosterSetFlags(flags);
}
}
@@ -292,10 +292,10 @@ public static void Run(string applicationName, int width, int height, bool fulls
MainThreadID = Thread.CurrentThread.ManagedThreadId;
if (fullscreen)
- App.flags |= Platform.FosterFlags.FULLSCREEN;
+ flags |= Platform.FosterFlags.Fullscreen;
- App.title = applicationName;
- App.Name = applicationName;
+ title = applicationName;
+ Name = applicationName;
var name = Platform.ToUTF8(applicationName);
Platform.FosterStartup(new()
@@ -305,23 +305,7 @@ public static void Run(string applicationName, int width, int height, bool fulls
width = width,
height = height,
renderer = renderer,
- flags = App.flags,
- onText = Input.OnText,
- onKey = Input.OnKey,
- onMouseButton = Input.OnMouseButton,
- onMouseMove = Input.OnMouseMove,
- onMouseWheel = Input.OnMouseWheel,
- onControllerConnect = Input.OnControllerConnect,
- onControllerDisconnect = Input.OnControllerDisconnect,
- onControllerButton = Input.OnControllerButton,
- onControllerAxis = Input.OnControllerAxis,
- onExitRequest = () =>
- {
- if (OnExitRequested != null)
- OnExitRequested();
- else
- Exit();
- }
+ flags = flags,
});
if(Platform.FosterIsRunning() == 0)
@@ -339,7 +323,7 @@ public static void Run(string applicationName, int width, int height, bool fulls
timer.Restart();
// poll events once, so input has controller state before Startup
- Platform.FosterPollEvents();
+ PollEvents();
Input.Step();
// register & startup all modules in order
@@ -377,6 +361,16 @@ public static void Run(string applicationName, int width, int height, bool fulls
Exiting = false;
}
+ ///
+ /// Notifies the Application to Exit.
+ /// The Application may finish the current frame before exiting.
+ ///
+ public static void Exit()
+ {
+ if (Running)
+ Exiting = true;
+ }
+
private static void Tick()
{
static void Update(TimeSpan delta)
@@ -386,7 +380,7 @@ static void Update(TimeSpan delta)
Graphics.Resources.DeleteRequested();
Input.Step();
- Platform.FosterPollEvents();
+ PollEvents();
FramePool.NextFrame();
for (int i = 0; i < modules.Count; i ++)
@@ -442,13 +436,32 @@ static void Update(TimeSpan delta)
Platform.FosterEndFrame();
}
- ///
- /// Notifies the Application to Exit.
- /// The Application may finish the current frame before exiting.
- ///
- public static void Exit()
+ private static void PollEvents()
{
- if (Running)
- Exiting = true;
+ while (Platform.FosterPollEvents(out var ev) != 0)
+ {
+ switch (ev.EventType)
+ {
+ case Platform.FosterEventType.None:
+ break;
+ case Platform.FosterEventType.ExitRequested:
+ if (OnExitRequested != null)
+ OnExitRequested();
+ else
+ Exit();
+ break;
+ case Platform.FosterEventType.KeyboardInput:
+ case Platform.FosterEventType.KeyboardKey:
+ case Platform.FosterEventType.MouseButton:
+ case Platform.FosterEventType.MouseMove:
+ case Platform.FosterEventType.MouseWheel:
+ case Platform.FosterEventType.ControllerConnect:
+ case Platform.FosterEventType.ControllerDisconnect:
+ case Platform.FosterEventType.ControllerButton:
+ case Platform.FosterEventType.ControllerAxis:
+ Input.OnFosterEvent(ev);
+ break;
+ }
+ }
}
}
diff --git a/Framework/Input/Input.cs b/Framework/Input/Input.cs
index 51d9644..33587cb 100644
--- a/Framework/Input/Input.cs
+++ b/Framework/Input/Input.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Numerics;
+using System.Runtime.InteropServices;
namespace Foster.Framework;
@@ -93,7 +94,7 @@ public static string GetClipboardString()
return Platform.ParseUTF8(ptr);
}
- internal static unsafe void OnText(IntPtr cstr)
+ private static unsafe void OnText(IntPtr cstr)
{
byte* ptr = (byte*)cstr;
if (ptr == null || ptr[0] == 0)
@@ -116,116 +117,118 @@ internal static unsafe void OnText(IntPtr cstr)
}
}
- ///
- /// Invoked by the Application platform when a Key state is changed
- ///
- internal static void OnKey(int key, byte pressed)
+ internal static unsafe void OnFosterEvent(in Platform.FosterEvent ev)
{
- if (key < 0 || key >= Keyboard.MaxKeys)
- throw new ArgumentOutOfRangeException(nameof(key), "Value is out of Range for supported keys");
-
- if (pressed != 0)
- {
- nextState.Keyboard.down[key] = true;
- nextState.Keyboard.pressed[key] = true;
- nextState.Keyboard.timestamp[key] = Time.Duration;
- }
- else
+ switch (ev.EventType)
{
- nextState.Keyboard.down[key] = false;
- nextState.Keyboard.released[key] = true;
- }
- }
-
- ///
- /// Invoked by the Application platform when a Mouse Button state is changed
- ///
- internal static void OnMouseButton(int button, byte pressed)
- {
- if (button < 0 || button >= Mouse.MaxButtons)
- throw new ArgumentOutOfRangeException(nameof(button), "Value is out of Range for supported mouse buttons");
-
- if (pressed != 0)
- {
- nextState.Mouse.down[button] = true;
- nextState.Mouse.pressed[button] = true;
- nextState.Mouse.timestamp[button] = Time.Duration;
- }
- else
- {
- nextState.Mouse.down[button] = false;
- nextState.Mouse.released[button] = true;
- }
- }
-
- ///
- /// Invoked by the Application platform when the Mouse Wheel state is changed
- ///
- internal static void OnMouseMove(float offsetX, float offsetY)
- {
- Point2 size = new Point2(App.Width, App.Height);
- Point2 pixels = new Point2(App.WidthInPixels, App.HeightInPixels);
-
- nextState.Mouse.Position.X = (offsetX / size.X) * pixels.X;
- nextState.Mouse.Position.Y = (offsetY / size.Y) * pixels.Y;
- }
-
- ///
- /// Invoked by the Application platform when the Mouse Wheel state is changed
- ///
- internal static void OnMouseWheel(float offsetX, float offsetY)
- {
- nextState.Mouse.wheelValue = new Vector2(offsetX, offsetY);
- }
-
- ///
- /// Invoked by the Application platform when a Controller is connected
- ///
- internal static void OnControllerConnect(int index, IntPtr name, int buttonCount, int axisCount, byte isGamepad, ushort vendor, ushort product, ushort version)
- {
- if (index >= 0 && index < InputState.MaxControllers)
- nextState.Controllers[index].Connect(Platform.ParseUTF8(name), buttonCount, axisCount, isGamepad != 0, vendor, product, version);
- }
-
- ///
- /// Invoked by the Application platform when a Controller is disconnected
- ///
- internal static void OnControllerDisconnect(int index)
- {
- if (index >= 0 && index < InputState.MaxControllers)
- nextState.Controllers[index].Disconnect();
- }
-
- ///
- /// Invoked by the Application platform when a Controller Button state is changed
- ///
- internal static void OnControllerButton(int index, int button, byte pressed)
- {
- if (index >= 0 && index < InputState.MaxControllers && button >= 0 && button < Controller.MaxButtons)
- {
- if (pressed != 0)
+ case Platform.FosterEventType.KeyboardInput:
{
- nextState.Controllers[index].down[button] = true;
- nextState.Controllers[index].pressed[button] = true;
- nextState.Controllers[index].timestamp[button] = Time.Duration;
+ fixed (byte* ptr = ev.Keyboard.Text)
+ OnText(new IntPtr(ptr));
+ break;
}
- else
+ case Platform.FosterEventType.KeyboardKey:
{
- nextState.Controllers[index].down[button] = false;
- nextState.Controllers[index].released[button] = true;
+ if (ev.Keyboard.Key >= 0 && ev.Keyboard.Key < Keyboard.MaxKeys)
+ {
+ if (ev.Keyboard.KeyPressed != 0)
+ {
+ nextState.Keyboard.down[ev.Keyboard.Key] = true;
+ nextState.Keyboard.pressed[ev.Keyboard.Key] = true;
+ nextState.Keyboard.timestamp[ev.Keyboard.Key] = Time.Duration;
+ }
+ else
+ {
+ nextState.Keyboard.down[ev.Keyboard.Key] = false;
+ nextState.Keyboard.released[ev.Keyboard.Key] = true;
+ }
+ }
+ break;
+ }
+ case Platform.FosterEventType.MouseButton:
+ {
+ if (ev.Mouse.Button >= 0 && ev.Mouse.Button < Mouse.MaxButtons)
+ {
+ if (ev.Mouse.ButtonPressed != 0)
+ {
+ nextState.Mouse.down[ev.Mouse.Button] = true;
+ nextState.Mouse.pressed[ev.Mouse.Button] = true;
+ nextState.Mouse.timestamp[ev.Mouse.Button] = Time.Duration;
+ }
+ else
+ {
+ nextState.Mouse.down[ev.Mouse.Button] = false;
+ nextState.Mouse.released[ev.Mouse.Button] = true;
+ }
+ }
+ break;
+ }
+ case Platform.FosterEventType.MouseMove:
+ {
+ var size = new Point2(App.Width, App.Height);
+ var pixels = new Point2(App.WidthInPixels, App.HeightInPixels);
+ nextState.Mouse.Position.X = (ev.Mouse.X / size.X) * pixels.X;
+ nextState.Mouse.Position.Y = (ev.Mouse.Y / size.Y) * pixels.Y;
+ break;
+ }
+ case Platform.FosterEventType.MouseWheel:
+ {
+ nextState.Mouse.wheelValue = new(ev.Mouse.X, ev.Mouse.Y);
+ break;
+ }
+ case Platform.FosterEventType.ControllerConnect:
+ {
+ if (ev.Controller.Index >= 0 && ev.Controller.Index < InputState.MaxControllers)
+ {
+ nextState.Controllers[ev.Controller.Index].Connect(
+ Platform.ParseUTF8(ev.Controller.Name),
+ ev.Controller.ButtonCount,
+ ev.Controller.AxisCount,
+ ev.Controller.IsGamepad != 0,
+ ev.Controller.Vendor,
+ ev.Controller.Product,
+ ev.Controller.Version
+ );
+ }
+ break;
+ }
+ case Platform.FosterEventType.ControllerDisconnect:
+ {
+ if (ev.Controller.Index >= 0 && ev.Controller.Index < InputState.MaxControllers)
+ nextState.Controllers[ev.Controller.Index].Disconnect();
+ break;
+ }
+ case Platform.FosterEventType.ControllerButton:
+ {
+ var index = ev.Controller.Index;
+ var button = ev.Controller.Button;
+ if (index >= 0 && index < InputState.MaxControllers && button >= 0 && button < Controller.MaxButtons)
+ {
+ if (ev.Controller.ButtonPressed != 0)
+ {
+ nextState.Controllers[index].down[button] = true;
+ nextState.Controllers[index].pressed[button] = true;
+ nextState.Controllers[index].timestamp[button] = Time.Duration;
+ }
+ else
+ {
+ nextState.Controllers[index].down[button] = false;
+ nextState.Controllers[index].released[button] = true;
+ }
+ }
+ break;
+ }
+ case Platform.FosterEventType.ControllerAxis:
+ {
+ var index = ev.Controller.Index;
+ var axis = ev.Controller.Axis;
+ if (index >= 0 && index < InputState.MaxControllers && axis >= 0 && axis < Controller.MaxAxis)
+ {
+ nextState.Controllers[index].axis[axis] = ev.Controller.AxisValue;
+ nextState.Controllers[index].axisTimestamp[axis] = Time.Duration;
+ }
+ break;
}
- }
- }
-
- ///
- /// Invoked by the Application platform when a Controller Axis state is changed
- ///
- internal static void OnControllerAxis(int index, int axis, float value)
- {
- if (index >= 0 && index < InputState.MaxControllers && axis >= 0 && axis < Controller.MaxAxis)
- {
- nextState.Controllers[index].axis[axis] = value;
- nextState.Controllers[index].axisTimestamp[axis] = Time.Duration;
}
}
}
diff --git a/Framework/Platform.cs b/Framework/Platform.cs
index 5ca37b7..63a6fb8 100644
--- a/Framework/Platform.cs
+++ b/Framework/Platform.cs
@@ -1,4 +1,5 @@
-using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Text;
namespace Foster.Framework;
@@ -10,44 +11,29 @@ internal static class Platform
[Flags]
public enum FosterFlags
{
- FULLSCREEN = 1 << 0,
- VSYNC = 1 << 1,
- RESIZABLE = 1 << 2,
- MOUSE_VISIBLE = 1 << 3,
+ Fullscreen = 1 << 0,
+ Vsync = 1 << 1,
+ Resizable = 1 << 2,
+ MouseVisible = 1 << 3,
}
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate void FosterLogFn(IntPtr msg);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate void FosterExitRequestFn();
+ public enum FosterEventType : int
+ {
+ None,
+ ExitRequested,
+ KeyboardInput,
+ KeyboardKey,
+ MouseButton,
+ MouseMove,
+ MouseWheel,
+ ControllerConnect,
+ ControllerDisconnect,
+ ControllerButton,
+ ControllerAxis
+ }
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate void FosterOnTextFn(IntPtr cstr);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate void FosterOnKeyFn(int key, byte pressed);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate void FosterOnMouseButtonFn(int button, byte pressed);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate void FosterOnMouseMoveFn(float posX, float posY);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate void FosterOnMouseWheelFn(float offsetX, float offsetY);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate void FosterOnControllerConnectFn(int index, IntPtr name, int buttonCount, int axisCount, byte isGamepad, ushort vendor, ushort product, ushort version);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate void FosterOnControllerDisconnectFn(int index);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate void FosterOnControllerButtonFn(int index, int button, byte pressed);
-
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate void FosterOnControllerAxisFn(int index, int axis, float value);
+ public delegate void FosterLogFn(IntPtr msg);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void FosterWriteFn(IntPtr context, IntPtr data, int size);
@@ -61,16 +47,52 @@ public struct FosterDesc
public int height;
public Renderers renderer;
public FosterFlags flags;
- public FosterExitRequestFn onExitRequest;
- public FosterOnTextFn onText;
- public FosterOnKeyFn onKey;
- public FosterOnMouseButtonFn onMouseButton;
- public FosterOnMouseMoveFn onMouseMove;
- public FosterOnMouseWheelFn onMouseWheel;
- public FosterOnControllerConnectFn onControllerConnect;
- public FosterOnControllerDisconnectFn onControllerDisconnect;
- public FosterOnControllerButtonFn onControllerButton;
- public FosterOnControllerAxisFn onControllerAxis;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct FosterEvent
+ {
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct KeyboardEvent
+ {
+ public FosterEventType EventType;
+ public fixed byte Text[32];
+ public int Key;
+ public byte KeyPressed;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct MouseEvent
+ {
+ public FosterEventType EventType;
+ public float X;
+ public float Y;
+ public int Button;
+ public byte ButtonPressed;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct ControllerEvent
+ {
+ public FosterEventType EventType;
+ public int Index;
+ public IntPtr Name;
+ public int ButtonCount;
+ public int AxisCount;
+ public byte IsGamepad;
+ public ushort Vendor;
+ public ushort Product;
+ public ushort Version;
+ public int Button;
+ public byte ButtonPressed;
+ public int Axis;
+ public float AxisValue;
+ }
+
+ [FieldOffset(0)] public FosterEventType EventType;
+ [FieldOffset(0)] public KeyboardEvent Keyboard;
+ [FieldOffset(0)] public MouseEvent Mouse;
+ [FieldOffset(0)] public ControllerEvent Controller;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
@@ -180,14 +202,14 @@ static Platform()
FosterRegisterLogMethods(logInfo, logWarn, logErr, 0);
}
- [DllImport(DLL)]
- public static extern void FosterRegisterLogMethods(FosterLogFn info, FosterLogFn warn, FosterLogFn error, int level);
[DllImport(DLL)]
public static extern void FosterStartup(FosterDesc desc);
[DllImport(DLL)]
+ public static extern void FosterRegisterLogMethods(FosterLogFn info, FosterLogFn warn, FosterLogFn error, int level);
+ [DllImport(DLL)]
public static extern void FosterBeginFrame();
[DllImport(DLL)]
- public static extern void FosterPollEvents();
+ public static extern byte FosterPollEvents(out FosterEvent fosterEvent);
[DllImport(DLL)]
public static extern void FosterEndFrame();
[DllImport(DLL)]
diff --git a/Platform/include/foster_platform.h b/Platform/include/foster_platform.h
index 857f84e..c79ec8f 100644
--- a/Platform/include/foster_platform.h
+++ b/Platform/include/foster_platform.h
@@ -400,17 +400,22 @@ typedef enum FosterImageWriteFormat
FOSTER_IMAGE_WRITE_FORMAT_QOI,
} FosterImageWriteFormat;
+typedef enum FosterEventType
+{
+ FOSTER_EVENT_TYPE_NONE,
+ FOSTER_EVENT_TYPE_EXIT_REQUESTED,
+ FOSTER_EVENT_TYPE_KEYBOARD_INPUT,
+ FOSTER_EVENT_TYPE_KEYBOARD_KEY,
+ FOSTER_EVENT_TYPE_MOUSE_BUTTON,
+ FOSTER_EVENT_TYPE_MOUSE_MOVE,
+ FOSTER_EVENT_TYPE_MOUSE_WHEEL,
+ FOSTER_EVENT_TYPE_CONTROLLER_CONNECT,
+ FOSTER_EVENT_TYPE_CONTROLLER_DISCONNECT,
+ FOSTER_EVENT_TYPE_CONTROLLER_BUTTON,
+ FOSTER_EVENT_TYPE_CONTROLLER_AXIS,
+} FosterEventType;
+
typedef void (FOSTER_CALL * FosterLogFn)(const char *msg);
-typedef void (FOSTER_CALL * FosterExitRequestFn)();
-typedef void (FOSTER_CALL * FosterOnTextFn)(const char* txt);
-typedef void (FOSTER_CALL * FosterOnKeyFn)(int key, FosterBool pressed);
-typedef void (FOSTER_CALL * FosterOnMouseButtonFn)(int button, FosterBool pressed);
-typedef void (FOSTER_CALL * FosterOnMouseMoveFn)(float posX, float posY);
-typedef void (FOSTER_CALL * FosterOnMouseWheelFn)(float offsetX, float offsetY);
-typedef void (FOSTER_CALL * FosterOnControllerConnectFn)(int index, const char* name, int buttonCount, int axisCount, FosterBool isGamepad, uint16_t vendor, uint16_t product, uint16_t version);
-typedef void (FOSTER_CALL * FosterOnControllerDisconnectFn)(int index);
-typedef void (FOSTER_CALL * FosterOnControllerButtonFn)(int index, int button, FosterBool pressed);
-typedef void (FOSTER_CALL * FosterOnControllerAxisFn)(int index, int axis, float value);
typedef void (FOSTER_CALL * FosterWriteFn)(void *context, void *data, int size);
typedef struct FosterTexture FosterTexture;
@@ -426,18 +431,48 @@ typedef struct FosterDesc
int height;
FosterRenderers renderer;
FosterFlags flags;
- FosterExitRequestFn onExitRequest;
- FosterOnTextFn onText;
- FosterOnKeyFn onKey;
- FosterOnMouseButtonFn onMouseButton;
- FosterOnMouseMoveFn onMouseMove;
- FosterOnMouseWheelFn onMouseWheel;
- FosterOnControllerConnectFn onControllerConnect;
- FosterOnControllerDisconnectFn onControllerDisconnect;
- FosterOnControllerButtonFn onControllerButton;
- FosterOnControllerAxisFn onControllerAxis;
} FosterDesc;
+typedef union FosterEvent
+{
+ int eventType;
+
+ struct
+ {
+ int eventType;
+ char text[32]; // intentionally the same size as SDL_TEXTINPUTEVENT_TEXT_SIZE
+ int key;
+ FosterBool keyPressed;
+ } keyboard;
+
+ struct
+ {
+ int eventType;
+ float x;
+ float y;
+ int button;
+ FosterBool buttonPressed;
+ } mouse;
+
+ struct
+ {
+ int eventType;
+ int index;
+ const char* name;
+ int buttonCount;
+ int axisCount;
+ FosterBool isGamepad;
+ uint16_t vendor;
+ uint16_t product;
+ uint16_t version;
+ int button;
+ FosterBool buttonPressed;
+ int axis;
+ float axisValue;
+ } controller;
+
+} FosterEvent;
+
typedef struct FosterRect
{
int x, y, w, h;
@@ -535,7 +570,7 @@ FOSTER_API void FosterRegisterLogMethods(FosterLogFn logInfo, FosterLogFn logWar
FOSTER_API void FosterBeginFrame();
-FOSTER_API void FosterPollEvents();
+FOSTER_API FosterBool FosterPollEvents(FosterEvent* ev);
FOSTER_API void FosterEndFrame();
diff --git a/Platform/libs/lib64/libFosterPlatform.so b/Platform/libs/lib64/libFosterPlatform.so
index 37679fb..85f2df3 100755
Binary files a/Platform/libs/lib64/libFosterPlatform.so and b/Platform/libs/lib64/libFosterPlatform.so differ
diff --git a/Platform/src/foster_internal.h b/Platform/src/foster_internal.h
index 58de205..98a34d9 100644
--- a/Platform/src/foster_internal.h
+++ b/Platform/src/foster_internal.h
@@ -22,6 +22,7 @@ typedef struct
FosterLogFn logWarn;
FosterLogFn logError;
FosterLogging logLevel;
+ FosterBool polledMouseMovement;
} FosterState;
FosterState* FosterGetState();
diff --git a/Platform/src/foster_platform.c b/Platform/src/foster_platform.c
index cda3a09..025e567 100644
--- a/Platform/src/foster_platform.c
+++ b/Platform/src/foster_platform.c
@@ -161,149 +161,188 @@ void FosterBeginFrame()
fstate.device.frameBegin();
}
-void FosterPollEvents()
+FosterBool FosterPollEvents(FosterEvent* output)
{
- FOSTER_ASSERT_RUNNING(FosterPollEvents);
+ FOSTER_ASSERT_RUNNING_RET(FosterPollEvents, 0);
- // always update the mouse position state
+ *output = (FosterEvent){ 0 };
+ output->eventType = FOSTER_EVENT_TYPE_NONE;
+
+ // Mouse Movement is always polled every time we poll events
+ // This way we track it even if SDL hasn't sent new mouse motion events
+ // TODO: should this just change to a getter?
+ if (!fstate.polledMouseMovement)
{
- int rel_x, rel_y;
- SDL_GetMouseState(&rel_x, &rel_y);
- fstate.desc.onMouseMove((float)(rel_x), (float)(rel_y));
+ int mouseX, mouseY;
+ SDL_GetMouseState(&mouseX, &mouseY);
+ output->eventType = FOSTER_EVENT_TYPE_MOUSE_MOVE;
+ output->mouse.x = (float)mouseX;
+ output->mouse.y = (float)mouseY;
+ fstate.polledMouseMovement = 1;
+ return 1;
}
+ // get next SDL event, or return false if no more found
+NEXT_EVENT:
SDL_Event event;
- while (SDL_PollEvent(&event))
+ if (!SDL_PollEvent(&event))
{
- if (event.type == SDL_QUIT)
- {
- if (fstate.desc.onExitRequest)
- fstate.desc.onExitRequest();
- }
- // Mouse
- else if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP)
- {
- FosterMouse btn = FosterGetMouseFromSDL(event.button.button);
- fstate.desc.onMouseButton(btn, event.type == SDL_MOUSEBUTTONDOWN);
- }
- else if (event.type == SDL_MOUSEWHEEL)
- {
- fstate.desc.onMouseWheel((float)event.wheel.x, (float)event.wheel.y);
- }
- // Keyboard
- else if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
- {
- if (event.key.repeat == 0)
- fstate.desc.onKey(FosterGetKeyFromSDL(event.key.keysym.scancode), event.type == SDL_KEYDOWN);
- }
- else if (event.type == SDL_TEXTINPUT)
- {
- fstate.desc.onText(event.text.text);
- }
- // Joystick Controller
- else if (event.type == SDL_JOYDEVICEADDED)
- {
- int index = event.jdevice.which;
-
- if (SDL_IsGameController(index) == SDL_FALSE && index >= 0 && index < FOSTER_MAX_CONTROLLERS)
- {
- SDL_Joystick* ptr = fstate.joysticks[index] = SDL_JoystickOpen(index);
- const char* name = SDL_JoystickName(ptr);
- int button_count = SDL_JoystickNumButtons(ptr);
- int axis_count = SDL_JoystickNumAxes(ptr);
- Uint16 vendor = SDL_JoystickGetVendor(ptr);
- Uint16 product = SDL_JoystickGetProduct(ptr);
- Uint16 version = SDL_JoystickGetProductVersion(ptr);
-
- fstate.desc.onControllerConnect(index, name, button_count, 0, axis_count, vendor, product, version);
- }
- }
- else if (event.type == SDL_JOYDEVICEREMOVED)
- {
- int index = FosterFindJoystickIndexSDL(fstate.joysticks, event.jdevice.which);
- if (index >= 0)
- {
- if (SDL_IsGameController(index) == SDL_FALSE)
- {
- fstate.desc.onControllerDisconnect(index);
- SDL_JoystickClose(fstate.joysticks[index]);
- }
- }
- }
- else if (event.type == SDL_JOYBUTTONDOWN || event.type == SDL_JOYBUTTONUP)
- {
- int index = FosterFindJoystickIndexSDL(fstate.joysticks, event.jdevice.which);
- if (index >= 0 && SDL_IsGameController(index) == SDL_FALSE)
- fstate.desc.onControllerButton(index, event.jbutton.button, event.type == SDL_JOYBUTTONDOWN);
- }
- else if (event.type == SDL_JOYAXISMOTION)
- {
- int index = FosterFindJoystickIndexSDL(fstate.joysticks, event.jdevice.which);
- if (index >= 0 && SDL_IsGameController(index) == SDL_FALSE)
- {
- float value;
- if (event.jaxis.value >= 0)
- value = event.jaxis.value / 32767.0f;
- else
- value = event.jaxis.value / 32768.0f;
- fstate.desc.onControllerAxis(index, event.jaxis.axis, value);
- }
- }
- // Gamepad Controller
- else if (event.type == SDL_CONTROLLERDEVICEADDED)
- {
- int index = event.cdevice.which;
-
- if (index >= 0 && index < FOSTER_MAX_CONTROLLERS)
- {
- SDL_GameController* ptr = fstate.gamepads[index] = SDL_GameControllerOpen(index);
- const char* name = SDL_GameControllerName(ptr);
- Uint16 vendor = SDL_GameControllerGetVendor(ptr);
- Uint16 product = SDL_GameControllerGetProduct(ptr);
- Uint16 version = SDL_GameControllerGetProductVersion(ptr);
-
- fstate.desc.onControllerConnect(index, name, 15, 6, 1, vendor, product, version);
- }
- }
- else if (event.type == SDL_CONTROLLERDEVICEREMOVED)
- {
- int index = FosterFindGamepadIndexSDL(fstate.gamepads, event.cdevice.which);
- if (index >= 0)
- {
- fstate.desc.onControllerDisconnect(index);
- SDL_GameControllerClose(fstate.gamepads[index]);
- }
- }
- else if (event.type == SDL_CONTROLLERBUTTONDOWN || event.type == SDL_CONTROLLERBUTTONUP)
- {
- int index = FosterFindGamepadIndexSDL(fstate.gamepads, event.cdevice.which);
- if (index >= 0)
- {
- FosterButtons button = FOSTER_BUTTON_NONE;
- if (event.cbutton.button >= 0 && event.cbutton.button < 15)
- button = FosterGetButtonFromSDL(event.cbutton.button);
- fstate.desc.onControllerButton(index, button, event.type == SDL_CONTROLLERBUTTONDOWN);
- }
- }
- else if (event.type == SDL_CONTROLLERAXISMOTION)
- {
- int index = FosterFindGamepadIndexSDL(fstate.gamepads, event.cdevice.which);
- if (index >= 0)
- {
- FosterAxis axis = FOSTER_AXIS_NONE;
- if (event.caxis.axis >= 0 && event.caxis.axis < 6)
- axis = FosterGetAxisFromSDL(event.caxis.axis);
-
- float value;
- if (event.caxis.value >= 0)
- value = event.caxis.value / 32767.0f;
- else
- value = event.caxis.value / 32768.0f;
-
- fstate.desc.onControllerAxis(index, axis, value);
- }
- }
+ fstate.polledMouseMovement = 0;
+ return 0;
+ }
+
+ // System Events
+ if (event.type == SDL_QUIT)
+ {
+ output->eventType = FOSTER_EVENT_TYPE_EXIT_REQUESTED;
}
+ // Mouse
+ else if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP)
+ {
+ output->eventType = FOSTER_EVENT_TYPE_MOUSE_BUTTON;
+ output->mouse.button = FosterGetMouseFromSDL(event.button.button);
+ output->mouse.buttonPressed = event.type == SDL_MOUSEBUTTONDOWN;
+ }
+ else if (event.type == SDL_MOUSEWHEEL)
+ {
+ output->eventType = FOSTER_EVENT_TYPE_MOUSE_WHEEL;
+ output->mouse.x = (float)event.wheel.x;
+ output->mouse.y = (float)event.wheel.y;
+ }
+ // Keyboard
+ else if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
+ {
+ if (event.key.repeat != 0)
+ goto NEXT_EVENT;
+
+ output->eventType = FOSTER_EVENT_TYPE_KEYBOARD_KEY;
+ output->keyboard.key = FosterGetKeyFromSDL(event.key.keysym.scancode);
+ output->keyboard.keyPressed = event.type == SDL_KEYDOWN;
+ }
+ else if (event.type == SDL_TEXTINPUT)
+ {
+ output->eventType = FOSTER_EVENT_TYPE_KEYBOARD_INPUT;
+ for (int i = 0; i < SDL_TEXTINPUTEVENT_TEXT_SIZE; i ++)
+ output->keyboard.text[i] = event.text.text[i];
+ }
+ // Joystick Controller
+ else if (event.type == SDL_JOYDEVICEADDED)
+ {
+ int index = event.jdevice.which;
+
+ if (SDL_IsGameController(index) || index < 0 || index >= FOSTER_MAX_CONTROLLERS)
+ goto NEXT_EVENT;
+
+ SDL_Joystick* ptr = fstate.joysticks[index] = SDL_JoystickOpen(index);
+
+ output->eventType = FOSTER_EVENT_TYPE_CONTROLLER_CONNECT;
+ output->controller.index = index;
+ output->controller.name = SDL_JoystickName(ptr);
+ output->controller.isGamepad = 0;
+ output->controller.buttonCount = SDL_JoystickNumButtons(ptr);
+ output->controller.axisCount = SDL_JoystickNumAxes(ptr);
+ output->controller.vendor = SDL_JoystickGetVendor(ptr);
+ output->controller.product = SDL_JoystickGetProduct(ptr);
+ output->controller.version = SDL_JoystickGetProductVersion(ptr);
+ }
+ else if (event.type == SDL_JOYDEVICEREMOVED)
+ {
+ int index = FosterFindJoystickIndexSDL(fstate.joysticks, event.jdevice.which);
+ if (index < 0 || SDL_IsGameController(index))
+ goto NEXT_EVENT;
+
+ output->eventType = FOSTER_EVENT_TYPE_CONTROLLER_DISCONNECT;
+ output->controller.index = index;
+ SDL_JoystickClose(fstate.joysticks[index]);
+ }
+ else if (event.type == SDL_JOYBUTTONDOWN || event.type == SDL_JOYBUTTONUP)
+ {
+ int index = FosterFindJoystickIndexSDL(fstate.joysticks, event.jdevice.which);
+ if (index < 0 || SDL_IsGameController(index))
+ goto NEXT_EVENT;
+
+ output->eventType = FOSTER_EVENT_TYPE_CONTROLLER_BUTTON;
+ output->controller.index = index;
+ output->controller.button = event.jbutton.button;
+ output->controller.buttonPressed = event.type == SDL_JOYBUTTONDOWN;
+ }
+ else if (event.type == SDL_JOYAXISMOTION)
+ {
+ int index = FosterFindJoystickIndexSDL(fstate.joysticks, event.jdevice.which);
+ if (index < 0 || SDL_IsGameController(index))
+ goto NEXT_EVENT;
+
+ output->eventType = FOSTER_EVENT_TYPE_CONTROLLER_AXIS;
+ output->controller.index = index;
+ output->controller.axis = event.jaxis.axis;
+ if (event.jaxis.value >= 0)
+ output->controller.axisValue = event.jaxis.value / 32767.0f;
+ else
+ output->controller.axisValue = event.jaxis.value / 32768.0f;
+ }
+ // Gamepad Controller
+ else if (event.type == SDL_CONTROLLERDEVICEADDED)
+ {
+ int index = event.cdevice.which;
+ if (index < 0 || index >= FOSTER_MAX_CONTROLLERS)
+ goto NEXT_EVENT;
+
+ SDL_GameController* ptr = fstate.gamepads[index] = SDL_GameControllerOpen(index);
+ output->eventType = FOSTER_EVENT_TYPE_CONTROLLER_CONNECT;
+ output->controller.index = index;
+ output->controller.name = SDL_GameControllerName(ptr);
+ output->controller.buttonCount = 15;
+ output->controller.axisCount = 6;
+ output->controller.isGamepad = 1;
+ output->controller.vendor = SDL_GameControllerGetVendor(ptr);
+ output->controller.product = SDL_GameControllerGetProduct(ptr);
+ output->controller.version = SDL_GameControllerGetProductVersion(ptr);
+ }
+ else if (event.type == SDL_CONTROLLERDEVICEREMOVED)
+ {
+ int index = FosterFindGamepadIndexSDL(fstate.gamepads, event.cdevice.which);
+ if (index < 0)
+ goto NEXT_EVENT;
+
+ output->eventType = FOSTER_EVENT_TYPE_CONTROLLER_DISCONNECT;
+ output->controller.index = index;
+ SDL_GameControllerClose(fstate.gamepads[index]);
+ }
+ else if (event.type == SDL_CONTROLLERBUTTONDOWN || event.type == SDL_CONTROLLERBUTTONUP)
+ {
+ int index = FosterFindGamepadIndexSDL(fstate.gamepads, event.cdevice.which);
+ if (index < 0)
+ goto NEXT_EVENT;
+
+ output->eventType = FOSTER_EVENT_TYPE_CONTROLLER_BUTTON;
+ output->controller.index = index;
+ output->controller.button = FOSTER_BUTTON_NONE;
+ if (event.cbutton.button >= 0 && event.cbutton.button < 15)
+ output->controller.button = FosterGetButtonFromSDL(event.cbutton.button);
+ output->controller.buttonPressed = event.type == SDL_CONTROLLERBUTTONDOWN;
+ }
+ else if (event.type == SDL_CONTROLLERAXISMOTION)
+ {
+ int index = FosterFindGamepadIndexSDL(fstate.gamepads, event.cdevice.which);
+ if (index < 0)
+ goto NEXT_EVENT;
+
+ output->eventType = FOSTER_EVENT_TYPE_CONTROLLER_AXIS;
+ output->controller.index = index;
+ output->controller.axis = FOSTER_AXIS_NONE;
+ if (event.caxis.axis >= 0 && event.caxis.axis < 6)
+ output->controller.axis = FosterGetAxisFromSDL(event.caxis.axis);
+ if (event.jaxis.value >= 0)
+ output->controller.axisValue = event.jaxis.value / 32767.0f;
+ else
+ output->controller.axisValue = event.jaxis.value / 32768.0f;
+ }
+ else
+ {
+ goto NEXT_EVENT;
+ }
+
+ return 1;
}
void FosterEndFrame()