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()