mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-09-23 06:53:43 +00:00
475 lines
14 KiB
C++
475 lines
14 KiB
C++
#include "SDL.h"
|
|
|
|
#include "GpMain.h"
|
|
#include "GpAudioDriverFactory.h"
|
|
#include "GpCursor_Win32.h"
|
|
#include "GpDisplayDriverFactory.h"
|
|
#include "GpGlobalConfig.h"
|
|
#include "GpFiber_Win32.h"
|
|
#include "GpFiber_SDL.h"
|
|
#include "GpFileSystem_Win32.h"
|
|
#include "GpLogDriver_Win32.h"
|
|
#include "GpFontHandlerFactory.h"
|
|
#include "GpInputDriverFactory.h"
|
|
#include "GpAppInterface.h"
|
|
#include "GpSystemServices_Win32.h"
|
|
#include "GpVOSEvent.h"
|
|
#include "IGpVOSEventQueue.h"
|
|
|
|
#include "HostFileSystem.h"
|
|
#include "HostThreadEvent.h"
|
|
|
|
#include "GpWindows.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include <shellapi.h>
|
|
#include <stdio.h>
|
|
#include <windowsx.h>
|
|
|
|
|
|
GpWindowsGlobals g_gpWindowsGlobals;
|
|
|
|
extern "C" __declspec(dllimport) IGpAudioDriver *GpDriver_CreateAudioDriver_XAudio2(const GpAudioDriverProperties &properties);
|
|
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);
|
|
|
|
static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t eventType, GpMouseButton_t button, int32_t x, int32_t y, float pixelScaleX, float pixelScaleY)
|
|
{
|
|
if (GpVOSEvent *evt = eventQueue->QueueEvent())
|
|
{
|
|
evt->m_eventType = GpVOSEventTypes::kMouseInput;
|
|
|
|
GpMouseInputEvent &mEvent = evt->m_event.m_mouseInputEvent;
|
|
mEvent.m_button = button;
|
|
mEvent.m_x = x;
|
|
mEvent.m_y = y;
|
|
mEvent.m_eventType = eventType;
|
|
|
|
if (pixelScaleX != 1.0f)
|
|
mEvent.m_x = static_cast<int32_t>(static_cast<float>(x) / pixelScaleX);
|
|
|
|
if (pixelScaleY != 1.0f)
|
|
mEvent.m_y = static_cast<int32_t>(static_cast<float>(y) / pixelScaleX);
|
|
}
|
|
}
|
|
|
|
static bool IdentifyVKey(const WPARAM &wparam, const LPARAM &lparam, GpKeyIDSubset_t &outSubset, GpKeyboardInputEvent::KeyUnion &outKey)
|
|
{
|
|
switch (wparam)
|
|
{
|
|
case VK_ESCAPE:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kEscape;
|
|
break;
|
|
case VK_PRINT:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kPrintScreen;
|
|
break;
|
|
case VK_SCROLL:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kScrollLock;
|
|
break;
|
|
case VK_PAUSE:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kPause;
|
|
break;
|
|
case VK_INSERT:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kInsert;
|
|
break;
|
|
case VK_HOME:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kHome;
|
|
break;
|
|
case VK_PRIOR:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kPageUp;
|
|
break;
|
|
case VK_NEXT:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kPageDown;
|
|
break;
|
|
case VK_DELETE:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kDelete;
|
|
break;
|
|
case VK_TAB:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kTab;
|
|
break;
|
|
case VK_END:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kEnd;
|
|
break;
|
|
case VK_BACK:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kBackspace;
|
|
break;
|
|
case VK_CAPITAL:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kCapsLock;
|
|
break;
|
|
case VK_RETURN:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kEnter;
|
|
break;
|
|
case VK_SHIFT:
|
|
{
|
|
UINT vkey = MapVirtualKeyW((lparam >> 16) & 0xff, MAPVK_VSC_TO_VK_EX);
|
|
|
|
if (vkey == VK_LSHIFT || vkey == VK_SHIFT)
|
|
{
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kLeftShift;
|
|
}
|
|
else if (vkey == VK_RSHIFT)
|
|
{
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kRightShift;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
break;
|
|
case VK_RSHIFT:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kRightShift;
|
|
break;
|
|
case VK_CONTROL:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
if (lparam & 0x01000000)
|
|
outKey.m_specialKey = GpKeySpecials::kRightCtrl;
|
|
else
|
|
outKey.m_specialKey = GpKeySpecials::kLeftCtrl;
|
|
break;
|
|
case VK_MENU:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
if (lparam & 0x01000000)
|
|
outKey.m_specialKey = GpKeySpecials::kRightAlt;
|
|
else
|
|
outKey.m_specialKey = GpKeySpecials::kLeftAlt;
|
|
break;
|
|
case VK_NUMLOCK:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kNumLock;
|
|
break;
|
|
case VK_NUMPAD0:
|
|
case VK_NUMPAD1:
|
|
case VK_NUMPAD2:
|
|
case VK_NUMPAD3:
|
|
case VK_NUMPAD4:
|
|
case VK_NUMPAD5:
|
|
case VK_NUMPAD6:
|
|
case VK_NUMPAD7:
|
|
case VK_NUMPAD8:
|
|
case VK_NUMPAD9:
|
|
outSubset = GpKeyIDSubsets::kNumPadNumber;
|
|
outKey.m_numPadNumber = static_cast<uint8_t>(wparam - VK_NUMPAD0);
|
|
break;
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
case 'A':
|
|
case 'B':
|
|
case 'C':
|
|
case 'D':
|
|
case 'E':
|
|
case 'F':
|
|
case 'G':
|
|
case 'H':
|
|
case 'I':
|
|
case 'J':
|
|
case 'K':
|
|
case 'L':
|
|
case 'M':
|
|
case 'N':
|
|
case 'O':
|
|
case 'P':
|
|
case 'Q':
|
|
case 'R':
|
|
case 'S':
|
|
case 'T':
|
|
case 'U':
|
|
case 'V':
|
|
case 'W':
|
|
case 'X':
|
|
case 'Y':
|
|
case 'Z':
|
|
outSubset = GpKeyIDSubsets::kASCII;
|
|
outKey.m_asciiChar = static_cast<char>(wparam);
|
|
break;
|
|
case VK_F1:
|
|
case VK_F2:
|
|
case VK_F3:
|
|
case VK_F4:
|
|
case VK_F5:
|
|
case VK_F6:
|
|
case VK_F7:
|
|
case VK_F8:
|
|
case VK_F9:
|
|
case VK_F10:
|
|
case VK_F11:
|
|
case VK_F12:
|
|
case VK_F13:
|
|
case VK_F14:
|
|
case VK_F15:
|
|
case VK_F16:
|
|
case VK_F17:
|
|
case VK_F18:
|
|
case VK_F19:
|
|
case VK_F20:
|
|
case VK_F21:
|
|
case VK_F22:
|
|
case VK_F23:
|
|
case VK_F24:
|
|
outSubset = GpKeyIDSubsets::kFKey;
|
|
outKey.m_fKey = static_cast<uint8_t>(wparam - VK_F1 + 1);
|
|
break;
|
|
case VK_OEM_COMMA:
|
|
outSubset = GpKeyIDSubsets::kASCII;
|
|
outKey.m_asciiChar = ',';
|
|
break;
|
|
case VK_OEM_MINUS:
|
|
outSubset = GpKeyIDSubsets::kASCII;
|
|
outKey.m_asciiChar = '-';
|
|
break;
|
|
case VK_OEM_PERIOD:
|
|
outSubset = GpKeyIDSubsets::kASCII;
|
|
outKey.m_asciiChar = '.';
|
|
break;
|
|
case VK_OEM_PLUS:
|
|
outSubset = GpKeyIDSubsets::kASCII;
|
|
outKey.m_asciiChar = '+';
|
|
break;
|
|
case VK_UP:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kUpArrow;
|
|
break;
|
|
case VK_DOWN:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kDownArrow;
|
|
break;
|
|
case VK_LEFT:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kLeftArrow;
|
|
break;
|
|
case VK_RIGHT:
|
|
outSubset = GpKeyIDSubsets::kSpecial;
|
|
outKey.m_specialKey = GpKeySpecials::kRightArrow;
|
|
break;
|
|
default:
|
|
{
|
|
if (wparam >= VK_OEM_1 && wparam <= VK_OEM_102)
|
|
{
|
|
UINT charCode = MapVirtualKeyW(static_cast<UINT>(wparam), MAPVK_VK_TO_CHAR);
|
|
if (charCode == 0)
|
|
return false;
|
|
|
|
if (charCode < 128)
|
|
{
|
|
outSubset = GpKeyIDSubsets::kASCII;
|
|
outKey.m_asciiChar = static_cast<char>(charCode);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
outSubset = GpKeyIDSubsets::kUnicode;
|
|
outKey.m_unicodeChar = charCode;;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static void PostKeyboardEvent(IGpVOSEventQueue *eventQueue, GpKeyboardInputEventType_t eventType, GpKeyIDSubset_t subset, const GpKeyboardInputEvent::KeyUnion &key, uint32_t repeatCount)
|
|
{
|
|
if (GpVOSEvent *evt = eventQueue->QueueEvent())
|
|
{
|
|
evt->m_eventType = GpVOSEventTypes::kKeyboardInput;
|
|
|
|
GpKeyboardInputEvent &mEvent = evt->m_event.m_keyboardInputEvent;
|
|
mEvent.m_key = key;
|
|
mEvent.m_eventType = eventType;
|
|
mEvent.m_keyIDSubset = subset;
|
|
mEvent.m_repeatCount = repeatCount;
|
|
}
|
|
}
|
|
|
|
static void TranslateWindowsMessage(const MSG *msg, IGpVOSEventQueue *eventQueue, float pixelScaleX, float pixelScaleY)
|
|
{
|
|
WPARAM wParam = msg->wParam;
|
|
LPARAM lParam = msg->lParam;
|
|
|
|
switch (msg->message)
|
|
{
|
|
case WM_LBUTTONDOWN:
|
|
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kLeft, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
|
break;
|
|
case WM_LBUTTONUP:
|
|
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kLeft, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
|
break;
|
|
case WM_MBUTTONDOWN:
|
|
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kMiddle, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
|
break;
|
|
case WM_MBUTTONUP:
|
|
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kMiddle, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
|
break;
|
|
case WM_RBUTTONDOWN:
|
|
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kRight, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
|
break;
|
|
case WM_RBUTTONUP:
|
|
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kRight, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
|
break;
|
|
case WM_XBUTTONDOWN:
|
|
if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)
|
|
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kX1, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
|
else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON2)
|
|
PostMouseEvent(eventQueue, GpMouseEventTypes::kDown, GpMouseButtons::kX2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
|
break;
|
|
case WM_XBUTTONUP:
|
|
if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)
|
|
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kX1, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
|
else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON2)
|
|
PostMouseEvent(eventQueue, GpMouseEventTypes::kUp, GpMouseButtons::kX2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
|
break;
|
|
case WM_MOUSEMOVE:
|
|
PostMouseEvent(eventQueue, GpMouseEventTypes::kMove, GpMouseButtons::kNone, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), pixelScaleX, pixelScaleY);
|
|
break;
|
|
case WM_MOUSELEAVE:
|
|
PostMouseEvent(eventQueue, GpMouseEventTypes::kLeave, GpMouseButtons::kNone, 0, 0, pixelScaleX, pixelScaleY);
|
|
break;
|
|
case WM_KEYDOWN:
|
|
case WM_SYSKEYDOWN:
|
|
{
|
|
GpKeyIDSubset_t subset;
|
|
GpKeyboardInputEvent::KeyUnion key;
|
|
bool isRepeat = ((lParam & 0x40000000) != 0);
|
|
const GpKeyboardInputEventType_t keyEventType = isRepeat ? GpKeyboardInputEventTypes::kAuto : GpKeyboardInputEventTypes::kDown;
|
|
if (IdentifyVKey(wParam, lParam, subset, key))
|
|
PostKeyboardEvent(eventQueue, keyEventType, subset, key, static_cast<uint32_t>(lParam & 0xffff));
|
|
|
|
(void)TranslateMessage(msg);
|
|
}
|
|
break;
|
|
case WM_KEYUP:
|
|
case WM_SYSKEYUP:
|
|
{
|
|
GpKeyIDSubset_t subset;
|
|
GpKeyboardInputEvent::KeyUnion key;
|
|
if (IdentifyVKey(wParam, lParam, subset, key))
|
|
PostKeyboardEvent(eventQueue, GpKeyboardInputEventTypes::kUp, subset, key, (lParam & 0xffff));
|
|
}
|
|
break;
|
|
case WM_CHAR:
|
|
case WM_UNICHAR:
|
|
{
|
|
bool isRepeat = ((lParam & 0x4000000) != 0);
|
|
const GpKeyboardInputEventType_t keyEventType = isRepeat ? GpKeyboardInputEventTypes::kAutoChar : GpKeyboardInputEventTypes::kDownChar;
|
|
GpKeyboardInputEvent::KeyUnion key;
|
|
GpKeyIDSubset_t subset = GpKeyIDSubsets::kASCII;
|
|
if (wParam <= 128)
|
|
key.m_asciiChar = static_cast<char>(wParam);
|
|
else
|
|
{
|
|
subset = GpKeyIDSubsets::kUnicode;
|
|
key.m_unicodeChar = static_cast<uint32_t>(wParam);
|
|
}
|
|
PostKeyboardEvent(eventQueue, keyEventType, subset, key, (lParam & 0xffff));
|
|
}
|
|
break;
|
|
case WM_QUIT:
|
|
{
|
|
if (GpVOSEvent *evt = eventQueue->QueueEvent())
|
|
evt->m_eventType = GpVOSEventTypes::kQuit;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
|
{
|
|
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
|
return -1;
|
|
|
|
LPWSTR cmdLine = GetCommandLineW();
|
|
|
|
int nArgs;
|
|
LPWSTR *cmdLineArgs = CommandLineToArgvW(cmdLine, &nArgs);
|
|
|
|
for (int i = 1; i < nArgs; i++)
|
|
{
|
|
if (!wcscmp(cmdLineArgs[i], L"-diagnostics"))
|
|
GpLogDriver_Win32::Init();
|
|
}
|
|
|
|
IGpLogDriver *logger = GpLogDriver_Win32::GetInstance();
|
|
|
|
GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Win32::GetInstance());
|
|
GpAppInterface_Get()->PL_HostSystemServices_SetInstance(GpSystemServices_Win32::GetInstance());
|
|
GpAppInterface_Get()->PL_HostLogDriver_SetInstance(GpLogDriver_Win32::GetInstance());
|
|
|
|
g_gpWindowsGlobals.m_hInstance = hInstance;
|
|
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
|
|
g_gpWindowsGlobals.m_cmdLine = cmdLine;
|
|
g_gpWindowsGlobals.m_cmdLineArgc = nArgs;
|
|
g_gpWindowsGlobals.m_cmdLineArgv = cmdLineArgs;
|
|
g_gpWindowsGlobals.m_nCmdShow = nCmdShow;
|
|
g_gpWindowsGlobals.m_baseDir = GpFileSystem_Win32::GetInstance()->GetBasePath();
|
|
g_gpWindowsGlobals.m_hwnd = nullptr;
|
|
//g_gpWindowsGlobals.m_hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_ICON1));
|
|
//g_gpWindowsGlobals.m_hIconSm = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_ICON2));
|
|
|
|
g_gpWindowsGlobals.m_loadCursorFunc = GpCursor_Win32::Load;
|
|
g_gpWindowsGlobals.m_translateWindowsMessageFunc = TranslateWindowsMessage;
|
|
|
|
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_SDL_GL2;
|
|
|
|
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_XAudio2;
|
|
|
|
g_gpGlobalConfig.m_fontHandlerType = EGpFontHandlerType_FreeType2;
|
|
|
|
EGpInputDriverType inputDrivers[] =
|
|
{
|
|
EGpInputDriverType_XInput
|
|
};
|
|
|
|
g_gpGlobalConfig.m_inputDriverTypes = inputDrivers;
|
|
g_gpGlobalConfig.m_numInputDrivers = sizeof(inputDrivers) / sizeof(inputDrivers[0]);
|
|
|
|
g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals;
|
|
g_gpGlobalConfig.m_logger = logger;
|
|
|
|
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_SDL_GL2, GpDriver_CreateDisplayDriver_SDL_GL2);
|
|
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_XAudio2, GpDriver_CreateAudioDriver_XAudio2);
|
|
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_XInput, GpDriver_CreateInputDriver_XInput);
|
|
GpFontHandlerFactory::RegisterFontHandlerFactory(EGpFontHandlerType_FreeType2, GpDriver_CreateFontHandler_FreeType2);
|
|
|
|
if (logger)
|
|
logger->Printf(IGpLogDriver::Category_Information, "SDL environment configured, starting up");
|
|
|
|
int returnCode = GpMain::Run();
|
|
|
|
if (logger)
|
|
logger->Printf(IGpLogDriver::Category_Information, "SDL environment exited with code %i, cleaning up", returnCode);
|
|
|
|
LocalFree(cmdLineArgs);
|
|
|
|
return returnCode;
|
|
}
|