Archived
1
Fork 0
This repository has been archived on 2025-04-12. You can view files and clone it, but cannot push or open issues or pull requests.
prism/platforms/windows/main.cpp.in
2020-09-23 10:17:24 -04:00

324 lines
7.1 KiB
C++
Executable file

#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include <windowsx.h>
#undef far
#undef near
#include "platform.hpp"
#include <gfx_vulkan.hpp>
#include <@APP_INCLUDE@>
#include <engine.hpp>
GFX* ginterface = nullptr;
@APP_CLASS@* app = nullptr;
HINSTANCE instance = NULL;
HWND window = NULL;
int cmdShow = 0;
HDC windowDC = NULL;
int defaultWidth, defaultHeight;
bool shouldConfineMouse = false;
const wchar_t CLASS_NAME[] = L"@APP_NAME@";
wchar_t* convertToUnicode(const char* str) {
size_t ret = 0;
mbsrtowcs_s(&ret, NULL, 0, &str, 0, NULL);
wchar_t * buf = new wchar_t[ret + 1]();
mbsrtowcs_s(&ret, buf, ret + 1 , &str, ret + 1, NULL);
return buf;
}
int platform::open_window(const std::string_view title, const prism::Rectangle rect, const WindowFlags flags) {
RECT wr = {rect.offset.x, rect.offset.y, rect.extent.width, rect.extent.height};
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
defaultWidth = rect.extent.width;
defaultHeight = rect.extent.height;
wchar_t* title_uni = convertToUnicode(title.data());
window = CreateWindowEx(
0,
CLASS_NAME,
title_uni,
flags == WindowFlags::Resizable ? WS_OVERLAPPEDWINDOW : (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX), // Window style
rect.offset.x,
rect.offset.y,
wr.right - wr.left,
wr.bottom - wr.top,
NULL,
NULL,
instance,
NULL
);
delete[] title_uni;
ShowWindow(window, cmdShow);
engine->add_window(window, 0, rect.extent);
app->initialize_render();
return 0;
}
void platform::close_window(const int identifier) {
// does nothing
}
bool showingCursor = true;
void platform::capture_mouse(const bool capture) {
shouldConfineMouse = capture;
// the reason why we do this is because windows expects a ShowCursor(false) to be followed by a ShowCursor(true),
// if you don't do this your cursor pretty much gets sent to bill gate's purgatory and it can never escape
// so this code is to ensure every ShowCursor call gets matched by it's counterpart when you call setCaptureMouse
if(showingCursor && capture) {
ShowCursor(false);
showingCursor = false;
} else if(!showingCursor && !capture) {
ShowCursor(true);
showingCursor = true;
}
}
prism::Offset platform::get_cursor_position() {
POINT p;
GetCursorPos(&p);
ScreenToClient(window, &p);
return {p.x, p.y};
}
prism::Offset platform::get_window_position(const int identifier) {
RECT rect;
GetWindowRect(window, &rect);
return {rect.left, rect.top};
}
prism::Extent platform::get_window_size(const int identifier) {
RECT rect;
GetClientRect(window, &rect);
int width = rect.right - rect.left;
int height = rect.bottom- rect.top;
return {static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow) {
AllocConsole();
FILE* stream;
freopen_s(&stream, "CONOUT$", "w", stdout);
freopen_s(&stream, "CONOUT$", "w", stderr);
WNDCLASS wc {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
instance = hInstance;
cmdShow = nCmdShow;
engine = new Engine(0, nullptr);
ginterface = new GFXVulkan();
if(ginterface->initialize(GFXCreateInfo())) {
engine->set_gfx(ginterface);
} else {
return -1;
}
app = new @APP_CLASS@();
engine->set_app(app);
app_main(engine);
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
delete app;
delete ginterface;
delete engine;
fclose(stream);
return 0;
}
int timeout = 0;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY:
{
engine->prepare_quit();
PostQuitMessage(0);
}
return 0;
case WM_PAINT:
{
if(shouldConfineMouse && timeout > 5) {
RECT rect;
GetClientRect(hwnd, &rect);
int width = rect.right - rect.left;
int height = rect.bottom- rect.top;
POINT p;
p.x = width / 2;
p.y = height / 2;
ClientToScreen(window, &p);
SetCursorPos(p.x, p.y);
timeout = 0;
}
timeout++;
HCURSOR arrowCursor = LoadCursor(NULL, IDC_ARROW);
SetCursor(arrowCursor);
engine->update(1.0f / 60.0f);
engine->begin_frame(1.0f / 60.0f);
engine->render(0);
if(engine->is_quitting()) {
engine->prepare_quit();
PostQuitMessage(0);
}
}
return 0;
case WM_LBUTTONDOWN:
{
int xPos = GET_X_LPARAM(lParam);
int yPos = GET_Y_LPARAM(lParam);
engine->process_mouse_down(0, {xPos, yPos});
}
return 0;
case WM_KEYDOWN:
{
engine->process_key_down((unsigned int)wParam);
}
return 0;
case WM_KEYUP:
{
engine->process_key_up((unsigned int)wParam);
}
return 0;
case WM_SIZE:
{
RECT rect;
GetClientRect(hwnd, &rect);
int width = rect.right - rect.left;
int height = rect.bottom- rect.top;
if(width == defaultWidth && height == defaultHeight) {
// don't resize when the window was first created!!
} else {
engine->resize(0, {static_cast<uint32_t>(width), static_cast<uint32_t>(height)});
}
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void platform::set_window_title(const int identifier, const std::string_view title) {
SetWindowTextA(window, title.data());
}
std::tuple<float, float> platform::get_right_stick_position() {
return {0.0f, 0.0f};
}
std::tuple<float, float> platform::get_left_stick_position() {
return {0.0f, 0.0f};
}
bool platform::is_window_focused(const int index) {
return false;
}
void platform::set_window_focused(const int index) {
}
prism::Extent platform::get_window_drawable_size(const int identifier) {
RECT rect;
GetClientRect(window, &rect);
int width = rect.right - rect.left;
int height = rect.bottom- rect.top;
return {static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
}
void platform::set_window_size(const int index, const prism::Extent extent) {
}
void platform::set_window_position(const int index, const prism::Offset offset) {
}
prism::Rectangle platform::get_monitor_resolution() {
return prism::Rectangle();
}
prism::Rectangle platform::get_monitor_work_area() {
return prism::Rectangle();
}
prism::Offset platform::get_screen_cursor_position() {
return prism::Offset();
}
float platform::get_window_dpi(const int index) {
return 1.0f;
}
bool platform::get_mouse_button_down(const int index) {
return false;
}
float platform::get_monitor_dpi() {
return 1.0f;
}
std::tuple<float, float> platform::get_wheel_delta() {
return {0.0f, 0.0f};
}