Fix fullscreen prefs not working in SDL. Add SDL GameController support.

This commit is contained in:
elasota
2021-03-05 01:56:32 -05:00
parent a5562f96e0
commit c981a97a20
14 changed files with 402 additions and 21 deletions

View File

@@ -95,6 +95,7 @@
<ClCompile Include="GpDisplayDriver_SDL_GL2.cpp" />
<ClCompile Include="GpFiberStarter_SDL.cpp" />
<ClCompile Include="GpFiber_SDL.cpp" />
<ClCompile Include="GpInputDriver_SDL_Gamepad.cpp" />
<ClCompile Include="GpMain_SDL_Win32.cpp" />
<ClCompile Include="ShaderCode\CopyQuadP.cpp" />
<ClCompile Include="ShaderCode\DrawQuad32P.cpp" />
@@ -112,15 +113,13 @@
<ProjectReference Include="..\GpFontHandler_FreeType2\GpFontHandler_FreeType2.vcxproj">
<Project>{4b564030-8985-4975-91e1-e1b2c16ae2a1}</Project>
</ProjectReference>
<ProjectReference Include="..\GpInputDriver_XInput\GpInputDriver_XInput.vcxproj">
<Project>{17b96f07-ef92-47cd-95a5-8e6ee38ab564}</Project>
</ProjectReference>
<ProjectReference Include="..\GpShell\GpShell.vcxproj">
<Project>{10cf9b5f-61d0-4b5b-89f4-810b58fc053d}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GpFiber_SDL.h" />
<ClInclude Include="GpInputDriver_SDL_Gamepad.h" />
<ClInclude Include="ShaderCode\DrawQuadPixelConstants.h" />
<ClInclude Include="ShaderCode\Functions.h" />
</ItemGroup>

View File

@@ -69,6 +69,9 @@
<ClCompile Include="ShaderCode\DrawQuad32P.cpp">
<Filter>Source Files\ShaderCode</Filter>
</ClCompile>
<ClCompile Include="GpInputDriver_SDL_Gamepad.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ShaderCode\Functions.h">
@@ -80,5 +83,8 @@
<ClInclude Include="GpFiber_SDL.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpInputDriver_SDL_Gamepad.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -6,6 +6,7 @@
#include "GpDisplayDriverProperties.h"
#include "GpVOSEvent.h"
#include "GpRingBuffer.h"
#include "GpInputDriver_SDL_Gamepad.h"
#include "IGpCursor.h"
#include "IGpDisplayDriverSurface.h"
#include "IGpLogDriver.h"
@@ -39,6 +40,13 @@ class GpDisplayDriver_SDL_GL2;
static GpDisplayDriverSurfaceEffects gs_defaultEffects;
static const char *kPrefsIdentifier = "GpDisplayDriverSDL_GL2";
static uint32_t kPrefsVersion = 1;
struct GpDisplayDriver_SDL_GL2_Prefs
{
bool m_isFullScreen;
};
namespace DeleteMe
{
@@ -1219,7 +1227,7 @@ GpDisplayDriver_SDL_GL2::GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties
m_bgColor[3] = 1.f;
// Stupid hack to detect mobile...
m_isFullScreenDesired = m_properties.m_systemServices->IsFullscreenPreferred();
m_isFullScreenDesired = m_properties.m_systemServices->IsFullscreenOnStartup();
const intmax_t periodNum = std::chrono::high_resolution_clock::period::num;
const intmax_t periodDen = std::chrono::high_resolution_clock::period::den;
@@ -1842,7 +1850,7 @@ void GpDisplayDriver_SDL_GL2::Run()
m_vosFiber = new GpFiber_SDL(nullptr, m_vosEvent);
uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
if (m_isFullScreenDesired)
if (m_properties.m_systemServices->IsFullscreenOnStartup())
{
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
m_isFullScreen = true;
@@ -1909,19 +1917,35 @@ void GpDisplayDriver_SDL_GL2::Run()
SDL_Event msg;
if (SDL_PollEvent(&msg) != 0)
{
if (msg.type == SDL_MOUSEMOTION)
switch (msg.type)
{
if (!m_mouseIsInClientArea)
m_mouseIsInClientArea = true;
}
//else if (msg.type == SDL_MOUSELEAVE) // Does SDL support this??
case SDL_MOUSEMOTION:
{
if (!m_mouseIsInClientArea)
m_mouseIsInClientArea = true;
}
break;
//case SDL_MOUSELEAVE: // Does SDL support this??
// m_mouseIsInClientArea = false;
else if (msg.type == SDL_RENDER_DEVICE_RESET || msg.type == SDL_RENDER_TARGETS_RESET)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to device loss (Type: %i)", static_cast<int>(msg.type));
// break;
case SDL_RENDER_DEVICE_RESET:
case SDL_RENDER_TARGETS_RESET:
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to device loss (Type: %i)", static_cast<int>(msg.type));
m_contextLost = true;
m_contextLost = true;
}
break;
case SDL_CONTROLLERAXISMOTION:
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERDEVICEADDED:
case SDL_CONTROLLERDEVICEREMOVED:
case SDL_CONTROLLERDEVICEREMAPPED:
if (IGpInputDriverSDLGamepad *gamepadDriver = IGpInputDriverSDLGamepad::GetInstance())
gamepadDriver->ProcessSDLEvent(msg);
break;
}
TranslateSDLMessage(&msg, m_properties.m_eventQueue, m_pixelScaleX, m_pixelScaleY, obstructiveTextInput);
@@ -2358,11 +2382,19 @@ bool GpDisplayDriver_SDL_GL2::SupportsSizedFormats() const
void GpDisplayDriver_SDL_GL2::ApplyPrefs(const void *identifier, size_t identifierSize, const void *contents, size_t contentsSize, uint32_t version)
{
if (version == kPrefsVersion && identifierSize == strlen(kPrefsIdentifier) && !memcmp(identifier, kPrefsIdentifier, identifierSize))
{
const GpDisplayDriver_SDL_GL2_Prefs *prefs = static_cast<const GpDisplayDriver_SDL_GL2_Prefs *>(contents);
m_isFullScreenDesired = prefs->m_isFullScreen;
}
}
bool GpDisplayDriver_SDL_GL2::SavePrefs(void *context, WritePrefsFunc_t writeFunc)
bool GpDisplayDriver_SDL_GL2::SavePrefs(void *context, IGpPrefsHandler::WritePrefsFunc_t writeFunc)
{
return true;
GpDisplayDriver_SDL_GL2_Prefs prefs;
prefs.m_isFullScreen = m_isFullScreenDesired;
return writeFunc(context, kPrefsIdentifier, strlen(kPrefsIdentifier), &prefs, sizeof(prefs), kPrefsVersion);
}
void GpDisplayDriver_SDL_GL2::UnlinkSurface(GpDisplayDriverSurface_GL2 *surface, GpDisplayDriverSurface_GL2 *prev, GpDisplayDriverSurface_GL2 *next)

View File

@@ -0,0 +1,309 @@
#include "GpInputDriver_SDL_Gamepad.h"
#include "GpVOSEvent.h"
#include "GpWindows.h"
#include "IGpVOSEventQueue.h"
#include "SDL_events.h"
#include "SDL_joystick.h"
#include "SDL_gamecontroller.h"
#include <stdlib.h>
#include <algorithm>
#include <new>
#include <vector>
class GpInputDriverSDLGamepad final : public IGpInputDriverSDLGamepad
{
public:
void ProcessInput() override;
void Shutdown() override;
IGpPrefsHandler *GetPrefsHandler() const override;
static GpInputDriverSDLGamepad *Create(const GpInputDriverProperties &props);
void ProcessSDLEvent(const SDL_Event &evt) override;
private:
static const int kMaxPlayers = 2;
GpInputDriverSDLGamepad(const GpInputDriverProperties &props);
~GpInputDriverSDLGamepad();
bool FindJoystickPlayer(uint8_t &playerNum, SDL_JoystickID joystickID);
void HandleDeviceAdded(SDL_JoystickID joystickID);
void HandleDeviceRemoved(SDL_JoystickID joystickID);
std::vector<GpVOSEvent> m_pendingEvents;
GpInputDriverProperties m_properties;
SDL_JoystickID m_playerJoystickIDs[kMaxPlayers];
SDL_GameController *m_playerControllers[kMaxPlayers];
bool m_playerButtonDown[kMaxPlayers][GpGamepadButtons::kCount];
};
static GpInputDriverSDLGamepad *gs_instance = nullptr;
IGpInputDriverSDLGamepad *IGpInputDriverSDLGamepad::GetInstance()
{
return gs_instance;
}
void GpInputDriverSDLGamepad::ProcessInput()
{
for (size_t i = 0; i < m_pendingEvents.size(); i++)
{
if (GpVOSEvent *evt = m_properties.m_eventQueue->QueueEvent())
*evt = m_pendingEvents[i];
}
m_pendingEvents.clear();
}
void GpInputDriverSDLGamepad::Shutdown()
{
this->~GpInputDriverSDLGamepad();
free(this);
gs_instance = nullptr;
}
IGpPrefsHandler *GpInputDriverSDLGamepad::GetPrefsHandler() const
{
return nullptr;
}
GpInputDriverSDLGamepad *GpInputDriverSDLGamepad::Create(const GpInputDriverProperties &props)
{
void *storage = malloc(sizeof(GpInputDriverSDLGamepad));
if (!storage)
return nullptr;
GpInputDriverSDLGamepad *driver = new (storage) GpInputDriverSDLGamepad(props);
gs_instance = driver;
return driver;
}
GpInputDriverSDLGamepad::GpInputDriverSDLGamepad(const GpInputDriverProperties &props)
: m_properties(props)
{
for (int i = 0; i < kMaxPlayers; i++)
{
m_playerJoystickIDs[i] = -1;
m_playerControllers[i] = nullptr;
for (int j = 0; j < GpGamepadButtons::kCount; j++)
m_playerButtonDown[i][j] = false;
}
}
GpInputDriverSDLGamepad::~GpInputDriverSDLGamepad()
{
for (int i = 0; i < kMaxPlayers; i++)
{
if (m_playerControllers[i])
SDL_GameControllerClose(m_playerControllers[i]);
}
}
bool GpInputDriverSDLGamepad::FindJoystickPlayer(uint8_t &playerNum, SDL_JoystickID joystickID)
{
for (int i = 0; i < kMaxPlayers; i++)
{
if (m_playerJoystickIDs[i] == joystickID)
{
playerNum = static_cast<uint8_t>(i);
return true;
}
}
return false;
}
void GpInputDriverSDLGamepad::HandleDeviceAdded(SDL_JoystickID joystickID)
{
for (int i = 0; i < kMaxPlayers; i++)
{
if (m_playerJoystickIDs[i] == -1)
{
SDL_GameController *controller = SDL_GameControllerOpen(joystickID);
if (controller)
{
m_playerJoystickIDs[i] = joystickID;
m_playerControllers[i] = controller;
}
return;
}
}
}
void GpInputDriverSDLGamepad::HandleDeviceRemoved(SDL_JoystickID joystickID)
{
int playerNum = 0;
bool foundPlayer = false;
for (int i = 0; i < kMaxPlayers; i++)
{
if (m_playerJoystickIDs[i] == joystickID)
{
SDL_GameControllerClose(m_playerControllers[i]);
m_playerJoystickIDs[i] = -1;
m_playerControllers[i] = nullptr;
playerNum = i;
foundPlayer = true;
}
}
if (!foundPlayer)
return;
for (int axis = 0; axis < GpGamepadAxes::kCount; axis++)
{
GpVOSEvent evt;
evt.m_eventType = GpVOSEventTypes::kGamepadInput;
evt.m_event.m_gamepadInputEvent.m_eventType = GpGamepadInputEventTypes::kAnalogAxisChanged;
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_axis = static_cast<GpGamepadAxis_t>(axis);
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_player = playerNum;
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_state = 0;
m_pendingEvents.push_back(evt);
}
for (int button = 0; button < GpGamepadButtons::kCount; button++)
{
if (m_playerButtonDown[playerNum][button])
{
m_playerButtonDown[playerNum][button] = false;
GpVOSEvent evt;
evt.m_eventType = GpVOSEventTypes::kKeyboardInput;
evt.m_event.m_keyboardInputEvent.m_eventType = GpKeyboardInputEventTypes::kUp;
evt.m_event.m_keyboardInputEvent.m_keyIDSubset = GpKeyIDSubsets::kGamepadButton;
evt.m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_player = playerNum;
evt.m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_button = static_cast<GpGamepadButton_t>(button);
evt.m_event.m_keyboardInputEvent.m_repeatCount = 0;
m_pendingEvents.push_back(evt);
}
}
}
void GpInputDriverSDLGamepad::ProcessSDLEvent(const SDL_Event &msg)
{
IGpVOSEventQueue *evtQueue = m_properties.m_eventQueue;
switch (msg.type)
{
case SDL_CONTROLLERAXISMOTION:
{
const SDL_ControllerAxisEvent &axisMsg = msg.caxis;
GpGamepadAxis_t axis = GpGamepadAxes::kCount;
uint8_t playerNumber = 0;
if (!FindJoystickPlayer(playerNumber, axisMsg.which))
break;
if (axisMsg.axis == SDL_CONTROLLER_AXIS_TRIGGERLEFT)
axis = GpGamepadAxes::kLeftTrigger;
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
axis = GpGamepadAxes::kRightTrigger;
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_LEFTX)
axis = GpGamepadAxes::kLeftStickX;
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_LEFTY)
axis = GpGamepadAxes::kLeftStickY;
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_RIGHTX)
axis = GpGamepadAxes::kRightStickX;
else if (axisMsg.axis == SDL_CONTROLLER_AXIS_RIGHTY)
axis = GpGamepadAxes::kRightStickY;
else
break;
GpVOSEvent evt;
evt.m_eventType = GpVOSEventTypes::kGamepadInput;
evt.m_event.m_gamepadInputEvent.m_eventType = GpGamepadInputEventTypes::kAnalogAxisChanged;
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_axis = axis;
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_player = playerNumber;
evt.m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_state = std::max<int16_t>(-32767, axisMsg.value);
m_pendingEvents.push_back(evt);
}
break;
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
{
const bool isDown = (msg.type == SDL_CONTROLLERBUTTONDOWN);
const SDL_ControllerButtonEvent &buttonMsg = msg.cbutton;
GpGamepadButton_t gpButton = GpGamepadButtons::kCount;
uint8_t playerNumber = 0;
if (!FindJoystickPlayer(playerNumber, buttonMsg.which))
break;
if (buttonMsg.button == SDL_CONTROLLER_BUTTON_A)
gpButton = GpGamepadButtons::kFaceRight;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_B)
gpButton = GpGamepadButtons::kFaceDown;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_X)
gpButton = GpGamepadButtons::kFaceUp;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_Y)
gpButton = GpGamepadButtons::kFaceLeft;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_START)
gpButton = GpGamepadButtons::kMisc1;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_BACK)
gpButton = GpGamepadButtons::kMisc2;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_LEFTSTICK)
gpButton = GpGamepadButtons::kLeftStick;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_RIGHTSTICK)
gpButton = GpGamepadButtons::kRightStick;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
gpButton = GpGamepadButtons::kLeftBumper;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
gpButton = GpGamepadButtons::kRightBumper;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
gpButton = GpGamepadButtons::kDPadUp;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
gpButton = GpGamepadButtons::kDPadDown;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
gpButton = GpGamepadButtons::kDPadLeft;
else if (buttonMsg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
gpButton = GpGamepadButtons::kDPadRight;
else
break;
m_playerButtonDown[playerNumber][gpButton] = isDown;
GpVOSEvent evt;
evt.m_eventType = GpVOSEventTypes::kKeyboardInput;
evt.m_event.m_keyboardInputEvent.m_eventType = (isDown ? GpKeyboardInputEventTypes::kDown : GpKeyboardInputEventTypes::kUp);
evt.m_event.m_keyboardInputEvent.m_keyIDSubset = GpKeyIDSubsets::kGamepadButton;
evt.m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_player = playerNumber;
evt.m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_button = gpButton;
evt.m_event.m_keyboardInputEvent.m_repeatCount = 0;
m_pendingEvents.push_back(evt);
}
break;
case SDL_CONTROLLERDEVICEADDED:
HandleDeviceAdded(msg.cdevice.which);
break;
case SDL_CONTROLLERDEVICEREMOVED:
HandleDeviceRemoved(msg.cdevice.which);
break;
case SDL_CONTROLLERDEVICEREMAPPED:
// Not really sure what to do here, just re-add it
HandleDeviceRemoved(msg.cdevice.which);
HandleDeviceAdded(msg.cdevice.which);
break;
}
}
IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties)
{
return GpInputDriverSDLGamepad::Create(properties);
}

View File

@@ -0,0 +1,14 @@
#pragma once
#include "IGpInputDriver.h"
#include "GpInputDriverProperties.h"
#include "GpVOSEvent.h"
union SDL_Event;
struct IGpInputDriverSDLGamepad : public IGpInputDriver
{
virtual void ProcessSDLEvent(const SDL_Event &evt) = 0;
static IGpInputDriverSDLGamepad *GetInstance();
};

View File

@@ -29,16 +29,16 @@
GpWindowsGlobals g_gpWindowsGlobals;
extern "C" __declspec(dllimport) IGpInputDriver *GpDriver_CreateInputDriver_XInput(const GpInputDriverProperties &properties);
extern "C" __declspec(dllimport) IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties);
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
IGpAudioDriver *GpDriver_CreateAudioDriver_SDL(const GpAudioDriverProperties &properties);
IGpInputDriver *GpDriver_CreateInputDriver_SDL2_Gamepad(const GpInputDriverProperties &properties);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0)
return -1;
LPWSTR cmdLine = GetCommandLineW();
@@ -79,7 +79,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
EGpInputDriverType inputDrivers[] =
{
EGpInputDriverType_XInput
EGpInputDriverType_SDL2_Gamepad
};
g_gpGlobalConfig.m_inputDriverTypes = inputDrivers;
@@ -91,7 +91,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_SDL2, GpDriver_CreateAudioDriver_SDL);
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_XInput, GpDriver_CreateInputDriver_XInput);
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_SDL2_Gamepad, GpDriver_CreateInputDriver_SDL2_Gamepad);
GpFontHandlerFactory::RegisterFontHandlerFactory(EGpFontHandlerType_FreeType2, GpDriver_CreateFontHandler_FreeType2);
if (logger)