2021-03-01 14:40:02 -05:00
|
|
|
#include <@APP_INCLUDE@>
|
|
|
|
#include <engine.hpp>
|
2021-05-11 17:38:09 -04:00
|
|
|
#include <chrono>
|
2021-03-01 14:40:02 -05:00
|
|
|
|
|
|
|
#include "gfx_vulkan.hpp"
|
|
|
|
#include "platform.hpp"
|
2021-04-20 00:23:14 -04:00
|
|
|
#include <string_utils.hpp>
|
2021-03-01 14:40:02 -05:00
|
|
|
|
2021-04-20 00:23:14 -04:00
|
|
|
#include <SDL.h>
|
|
|
|
#include <SDL_vulkan.h>
|
2021-03-01 14:40:02 -05:00
|
|
|
|
2021-05-11 16:11:23 -04:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
#include <winrt/Windows.UI.ViewManagement.h>
|
|
|
|
#pragma comment(lib, "windowsapp")
|
|
|
|
#endif
|
|
|
|
|
2021-03-01 14:40:02 -05:00
|
|
|
@APP_CLASS@* app = nullptr;
|
2021-04-20 00:23:14 -04:00
|
|
|
GFX* gfx_interface = nullptr;
|
2021-03-01 14:40:02 -05:00
|
|
|
|
|
|
|
struct Window {
|
|
|
|
int identifier = 0;
|
|
|
|
SDL_Window* window = nullptr;
|
2021-04-20 00:23:14 -04:00
|
|
|
|
|
|
|
bool operator==(const Window& b) {
|
|
|
|
return identifier == b.identifier && window == b.window;
|
|
|
|
}
|
2021-03-01 14:40:02 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<Window> windows;
|
|
|
|
|
2021-04-20 00:23:14 -04:00
|
|
|
Window* get_window(const int index) {
|
|
|
|
for(auto& window : windows) {
|
|
|
|
if(window.identifier == index)
|
|
|
|
return &window;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-04-20 00:47:04 -04:00
|
|
|
Window* get_window_by_sdl_id(const Uint32 id) {
|
|
|
|
for(auto& window : windows) {
|
|
|
|
if(SDL_GetWindowID(window.window) == id)
|
|
|
|
return &window;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-03-01 14:40:02 -05:00
|
|
|
static std::map<InputButton, int> inputToKeyCode = { {
|
2021-04-20 01:14:33 -04:00
|
|
|
{InputButton::C, SDL_SCANCODE_C},
|
|
|
|
{InputButton::V, SDL_SCANCODE_V},
|
|
|
|
{InputButton::X, SDL_SCANCODE_X},
|
|
|
|
{InputButton::Y, SDL_SCANCODE_Y},
|
|
|
|
{InputButton::Z, SDL_SCANCODE_Z},
|
|
|
|
{InputButton::Backspace, SDL_SCANCODE_BACKSPACE},
|
|
|
|
{InputButton::Enter, SDL_SCANCODE_RETURN},
|
|
|
|
{InputButton::W, SDL_SCANCODE_W},
|
|
|
|
{InputButton::A, SDL_SCANCODE_A},
|
|
|
|
{InputButton::S, SDL_SCANCODE_S},
|
|
|
|
{InputButton::D, SDL_SCANCODE_D},
|
|
|
|
{InputButton::Q, SDL_SCANCODE_Q},
|
|
|
|
{InputButton::Shift, SDL_SCANCODE_LSHIFT},
|
|
|
|
{InputButton::Alt, SDL_SCANCODE_LALT},
|
|
|
|
{InputButton::Super, SDL_SCANCODE_APPLICATION},
|
|
|
|
{InputButton::Escape, SDL_SCANCODE_ESCAPE},
|
|
|
|
{InputButton::Tab, SDL_SCANCODE_TAB},
|
|
|
|
{InputButton::Ctrl, SDL_SCANCODE_LCTRL},
|
|
|
|
{InputButton::Space, SDL_SCANCODE_SPACE},
|
|
|
|
{InputButton::LeftArrow, SDL_SCANCODE_LEFT},
|
|
|
|
{InputButton::RightArrow, SDL_SCANCODE_RIGHT}
|
2021-03-01 14:40:02 -05:00
|
|
|
}};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Platform functions"
|
|
|
|
*/
|
|
|
|
|
|
|
|
const char* platform::get_name() {
|
2021-04-20 01:14:33 -04:00
|
|
|
return SDL_GetPlatform();
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
bool platform::supports_feature(const PlatformFeature feature) {
|
|
|
|
if(feature == PlatformFeature::Windowing)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int platform::open_window(const std::string_view title, const prism::Rectangle rect, const WindowFlags flags) {
|
|
|
|
auto& win = windows.emplace_back();
|
|
|
|
win.identifier = windows.size() - 1;
|
|
|
|
|
2021-04-20 00:47:04 -04:00
|
|
|
int sdl_flags = SDL_WINDOW_VULKAN;
|
|
|
|
if(flags == WindowFlags::Borderless)
|
|
|
|
sdl_flags |= SDL_WINDOW_BORDERLESS;
|
|
|
|
if(flags == WindowFlags::Resizable)
|
|
|
|
sdl_flags |= SDL_WINDOW_RESIZABLE;
|
|
|
|
|
2021-04-20 12:57:59 -04:00
|
|
|
int real_x = rect.offset.x;
|
|
|
|
int real_y = rect.offset.y;
|
|
|
|
if(rect.offset.x == -1 && rect.offset.y == -1) {
|
|
|
|
real_x = SDL_WINDOWPOS_CENTERED;
|
|
|
|
real_y = SDL_WINDOWPOS_CENTERED;
|
|
|
|
}
|
|
|
|
|
|
|
|
win.window = SDL_CreateWindow(title.data(), real_x, real_y, rect.extent.width, rect.extent.height, sdl_flags);
|
2021-03-01 14:40:02 -05:00
|
|
|
|
2021-04-20 00:47:04 -04:00
|
|
|
engine->add_window((void*)&win, win.identifier, rect.extent);
|
2021-03-01 14:40:02 -05:00
|
|
|
app->initialize_render();
|
|
|
|
|
|
|
|
return win.identifier;
|
|
|
|
}
|
|
|
|
|
|
|
|
void platform::close_window(const int index) {
|
2021-04-20 00:23:14 -04:00
|
|
|
auto window = get_window(index);
|
|
|
|
|
|
|
|
engine->remove_window(window->identifier);
|
|
|
|
|
|
|
|
SDL_DestroyWindow(window->window);
|
|
|
|
|
|
|
|
utility::erase(windows, *window);
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void platform::force_quit() {
|
2021-04-20 01:14:33 -04:00
|
|
|
SDL_Quit();
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
float platform::get_window_dpi(const int index) {
|
|
|
|
return 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
float platform::get_monitor_dpi() {
|
|
|
|
return 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
prism::Rectangle platform::get_monitor_resolution() {
|
2021-04-20 00:23:14 -04:00
|
|
|
SDL_DisplayMode DM;
|
|
|
|
SDL_GetCurrentDisplayMode(0, &DM);
|
|
|
|
|
|
|
|
return {0, 0, (uint32_t)DM.w, (uint32_t)DM.h};
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
prism::Rectangle platform::get_monitor_work_area() {
|
|
|
|
return platform::get_monitor_resolution();
|
|
|
|
}
|
|
|
|
|
2021-04-20 00:23:14 -04:00
|
|
|
prism::Offset platform::get_window_position(const int index) {
|
|
|
|
auto window = get_window(index);
|
2021-03-01 14:40:02 -05:00
|
|
|
|
2021-04-20 00:23:14 -04:00
|
|
|
int x, y;
|
|
|
|
SDL_GetWindowPosition(window->window, &x, &y);
|
2021-03-01 14:40:02 -05:00
|
|
|
|
2021-04-20 00:23:14 -04:00
|
|
|
return {(int32_t)x, (int32_t)y};
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
prism::Extent platform::get_window_size(const int index) {
|
|
|
|
auto window = get_window(index);
|
|
|
|
|
|
|
|
int width, height;
|
|
|
|
SDL_GetWindowSize(window->window, &width, &height);
|
|
|
|
|
|
|
|
return {(uint32_t)width, (uint32_t)height};
|
|
|
|
}
|
|
|
|
|
|
|
|
prism::Extent platform::get_window_drawable_size(const int index) {
|
|
|
|
auto window = get_window(index);
|
|
|
|
|
|
|
|
int width, height;
|
|
|
|
SDL_GetWindowSize(window->window, &width, &height);
|
|
|
|
|
|
|
|
return {(uint32_t)width, (uint32_t)height};
|
|
|
|
}
|
|
|
|
|
|
|
|
bool platform::is_window_focused(const int index) {
|
2021-04-20 01:14:33 -04:00
|
|
|
auto window = get_window(index);
|
|
|
|
return (SDL_GetWindowFlags(window->window) & SDL_WINDOW_INPUT_FOCUS) != 0;
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void platform::set_window_focused(const int index) {
|
2021-04-20 00:23:14 -04:00
|
|
|
auto window = get_window(index);
|
2021-04-20 01:14:33 -04:00
|
|
|
SDL_RaiseWindow(window->window);
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void platform::set_window_position(const int index, const prism::Offset offset) {
|
2021-04-20 00:23:14 -04:00
|
|
|
auto window = get_window(index);
|
|
|
|
|
|
|
|
SDL_SetWindowPosition(window->window, offset.x, offset.y);
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void platform::set_window_size(const int index, const prism::Extent extent) {
|
2021-04-20 00:23:14 -04:00
|
|
|
auto window = get_window(index);
|
|
|
|
|
|
|
|
SDL_SetWindowSize(window->window, extent.width, extent.height);
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void platform::set_window_title(const int index, const std::string_view title) {
|
|
|
|
auto window = get_window(index);
|
|
|
|
|
|
|
|
SDL_SetWindowTitle(window->window, title.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool platform::get_key_down(const InputButton key) {
|
2021-04-20 01:14:33 -04:00
|
|
|
const Uint8 *state = SDL_GetKeyboardState(NULL);
|
|
|
|
|
|
|
|
return state[inputToKeyCode[key]] && state[SDL_SCANCODE_DOWN];
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
int platform::get_keycode(const InputButton key) {
|
|
|
|
return inputToKeyCode[key];
|
|
|
|
}
|
|
|
|
|
|
|
|
prism::Offset platform::get_cursor_position() {
|
2021-04-20 00:23:14 -04:00
|
|
|
int x, y;
|
|
|
|
SDL_GetMouseState(&x, &y);
|
|
|
|
|
|
|
|
return {(int32_t)x, (int32_t)y};
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
prism::Offset platform::get_screen_cursor_position() {
|
2021-04-20 00:23:14 -04:00
|
|
|
int x, y;
|
|
|
|
SDL_GetGlobalMouseState(&x, &y);
|
|
|
|
|
|
|
|
return {(int32_t)x, (int32_t)y};
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
bool platform::get_mouse_button_down(const int button) {
|
2021-05-11 17:05:29 -04:00
|
|
|
Uint8 sdl_button = SDL_BUTTON_LEFT;
|
|
|
|
switch(button) {
|
|
|
|
case 0:
|
|
|
|
sdl_button = SDL_BUTTON_LEFT;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
sdl_button = SDL_BUTTON_RIGHT;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
sdl_button = SDL_BUTTON_MIDDLE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(sdl_button)) != 0;
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
2021-04-20 01:14:33 -04:00
|
|
|
float mouse_wheel_x, mouse_wheel_y;
|
|
|
|
|
2021-03-01 14:40:02 -05:00
|
|
|
std::tuple<float, float> platform::get_wheel_delta() {
|
2021-04-20 01:14:33 -04:00
|
|
|
return {mouse_wheel_x, mouse_wheel_y};
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
std::tuple<float, float> platform::get_right_stick_position() {
|
2021-04-20 00:23:14 -04:00
|
|
|
return {0.0f, 0.0f};
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
std::tuple<float, float> platform::get_left_stick_position() {
|
2021-04-20 00:23:14 -04:00
|
|
|
return {0.0f, 0.0f};
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void platform::capture_mouse(const bool capture) {
|
2021-04-20 01:14:33 -04:00
|
|
|
SDL_CaptureMouse((SDL_bool)capture);
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
char* platform::translate_keycode(const unsigned int keycode) {
|
2021-10-07 17:46:28 -04:00
|
|
|
return const_cast<char*>(SDL_GetKeyName(SDL_GetKeyFromScancode((SDL_Scancode)keycode)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void platform::begin_text_input() {
|
|
|
|
SDL_StartTextInput();
|
|
|
|
}
|
|
|
|
|
|
|
|
void platform::end_text_input() {
|
|
|
|
SDL_StopTextInput();
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
2021-04-20 01:14:33 -04:00
|
|
|
void platform::mute_output() {}
|
2021-03-01 14:40:02 -05:00
|
|
|
|
2021-04-20 01:14:33 -04:00
|
|
|
void platform::unmute_output() {}
|
2021-03-01 14:40:02 -05:00
|
|
|
|
|
|
|
int main(int argc, char* argv[]) {
|
2021-05-11 17:38:09 -04:00
|
|
|
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
2021-03-01 14:40:02 -05:00
|
|
|
|
2021-04-20 00:23:14 -04:00
|
|
|
engine = new prism::engine(argc, argv);
|
2021-03-01 14:40:02 -05:00
|
|
|
|
|
|
|
app = new @APP_CLASS@();
|
|
|
|
engine->set_app(app);
|
|
|
|
|
|
|
|
GFXCreateInfo info = {};
|
|
|
|
|
2021-04-20 00:23:14 -04:00
|
|
|
gfx_interface = new GFXVulkan();
|
|
|
|
if(gfx_interface->initialize(info)) {
|
|
|
|
engine->set_gfx(gfx_interface);
|
2021-03-01 14:40:02 -05:00
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
app_main(engine);
|
|
|
|
|
2021-05-11 17:38:09 -04:00
|
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
|
|
|
2021-04-20 00:47:04 -04:00
|
|
|
while(!engine->is_quitting()) {
|
2021-03-01 14:40:02 -05:00
|
|
|
SDL_Event event = {};
|
|
|
|
while(SDL_PollEvent(&event)) {
|
2021-04-20 00:47:04 -04:00
|
|
|
switch(event.type) {
|
|
|
|
case SDL_QUIT:
|
|
|
|
engine->quit();
|
|
|
|
break;
|
2021-04-20 01:14:33 -04:00
|
|
|
case SDL_MOUSEWHEEL: {
|
|
|
|
mouse_wheel_x = event.wheel.x;
|
|
|
|
mouse_wheel_y = event.wheel.y;
|
|
|
|
}
|
|
|
|
break;
|
2021-05-11 17:05:29 -04:00
|
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
|
|
{
|
|
|
|
int engine_button = 0;
|
|
|
|
if(event.button.button == SDL_BUTTON_RIGHT)
|
|
|
|
engine_button = 1;
|
|
|
|
else if(event.button.button == SDL_BUTTON_MIDDLE)
|
|
|
|
engine_button = 2;
|
|
|
|
|
|
|
|
engine->process_mouse_down(engine_button, {0, 0});
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SDL_KEYDOWN:
|
|
|
|
{
|
|
|
|
engine->process_key_down(event.key.keysym.scancode);
|
|
|
|
}
|
|
|
|
break;
|
2021-10-07 17:46:28 -04:00
|
|
|
case SDL_KEYUP:
|
|
|
|
{
|
|
|
|
engine->process_key_up(event.key.keysym.scancode);
|
|
|
|
}
|
|
|
|
break;
|
2021-04-20 00:47:04 -04:00
|
|
|
case SDL_WINDOWEVENT:
|
2021-10-07 17:46:28 -04:00
|
|
|
{
|
2021-04-20 00:47:04 -04:00
|
|
|
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
|
|
|
|
auto window = get_window_by_sdl_id(event.window.windowID);
|
|
|
|
if(window != nullptr)
|
|
|
|
engine->resize(window->identifier, {static_cast<uint32_t>(event.window.data1), static_cast<uint32_t>(event.window.data2)});
|
2021-04-20 12:57:59 -04:00
|
|
|
} else if(event.window.event == SDL_WINDOWEVENT_CLOSE) {
|
|
|
|
engine->quit();
|
2021-04-20 00:47:04 -04:00
|
|
|
}
|
2021-10-07 17:46:28 -04:00
|
|
|
}
|
2021-04-20 00:47:04 -04:00
|
|
|
break;
|
2021-10-07 17:46:28 -04:00
|
|
|
case SDL_TEXTINPUT:
|
|
|
|
{
|
|
|
|
engine->process_text_input(event.text.text);
|
|
|
|
}
|
|
|
|
break;
|
2021-04-20 00:47:04 -04:00
|
|
|
}
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if(engine->is_quitting())
|
|
|
|
break;
|
|
|
|
|
2021-05-11 17:38:09 -04:00
|
|
|
auto begin = std::chrono::high_resolution_clock::now();
|
|
|
|
|
|
|
|
float deltatime = (float)std::chrono::duration_cast<std::chrono::nanoseconds>(begin - end).count() / 1000000000ULL;
|
|
|
|
end = begin;
|
|
|
|
|
|
|
|
engine->update(deltatime);
|
|
|
|
engine->begin_frame(deltatime);
|
2021-04-20 00:47:04 -04:00
|
|
|
|
2021-05-11 17:38:09 -04:00
|
|
|
for(auto window : windows)
|
2021-04-20 00:47:04 -04:00
|
|
|
engine->render(window.identifier);
|
2021-03-01 14:40:02 -05:00
|
|
|
|
2021-05-11 17:38:09 -04:00
|
|
|
engine->end_frame();
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
2021-06-01 12:44:16 -04:00
|
|
|
engine->prepare_quit();
|
|
|
|
|
|
|
|
return 0;
|
2021-03-01 14:40:02 -05:00
|
|
|
}
|
|
|
|
|
2021-05-11 16:11:23 -04:00
|
|
|
#ifdef PLATFORM_WINDOWS
|
|
|
|
PlatformTheme platform::get_theme() {
|
|
|
|
using namespace winrt::Windows::UI::ViewManagement;
|
|
|
|
|
|
|
|
// TODO: figure out if this works pre-anniversary update/other windows other than 10
|
|
|
|
UISettings settings;
|
|
|
|
auto background = settings.GetColorValue(UIColorType::Background);
|
|
|
|
auto foreground = settings.GetColorValue(UIColorType::Foreground);
|
|
|
|
|
|
|
|
if (background == winrt::Windows::UI::Colors::White())
|
|
|
|
return PlatformTheme::Light;
|
|
|
|
else
|
|
|
|
return PlatformTheme::Dark;
|
|
|
|
}
|
|
|
|
#else
|
2021-03-01 14:40:02 -05:00
|
|
|
PlatformTheme platform::get_theme() {
|
|
|
|
return PlatformTheme::Light;
|
|
|
|
}
|
2021-05-11 16:11:23 -04:00
|
|
|
#endif
|
2021-03-01 14:40:02 -05:00
|
|
|
|
|
|
|
void* platform::create_native_surface(int index, void* instance) {
|
|
|
|
auto window = get_window(index);
|
|
|
|
|
|
|
|
VkSurfaceKHR surface;
|
|
|
|
|
|
|
|
SDL_Vulkan_CreateSurface(window->window, (VkInstance)instance, &surface);
|
|
|
|
|
|
|
|
return surface;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<const char*> platform::get_native_surface_extension() {
|
|
|
|
// dummy window
|
|
|
|
auto dummy = SDL_CreateWindow("", 0, 0, 1, 1, SDL_WINDOW_VULKAN);
|
|
|
|
|
|
|
|
unsigned int count = 0;
|
|
|
|
SDL_Vulkan_GetInstanceExtensions(dummy, &count, nullptr);
|
|
|
|
|
|
|
|
std::vector<const char*> extensions(count);
|
|
|
|
SDL_Vulkan_GetInstanceExtensions(dummy, &count, extensions.data());
|
|
|
|
|
|
|
|
SDL_DestroyWindow(dummy);
|
|
|
|
|
|
|
|
return extensions;
|
|
|
|
}
|