349 lines
9.2 KiB
C++
Executable file
349 lines
9.2 KiB
C++
Executable file
#include <@APP_INCLUDE@>
|
|
#include <engine.hpp>
|
|
|
|
#include "gfx_vulkan.hpp"
|
|
#include "platform.hpp"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <X11/Xlib.h>
|
|
#include <xcb/xcb.h>
|
|
#include <X11/Xutil.h>
|
|
#include <GL/gl.h>
|
|
#include <GL/glx.h>
|
|
|
|
@APP_CLASS@* app = nullptr;
|
|
GFX* interface = nullptr;
|
|
|
|
Display *dpy = nullptr;
|
|
|
|
int mouse_x = -1, mouse_y = -1;
|
|
bool mouse_down[2] = {false, false};
|
|
|
|
xcb_connection_t* connection = nullptr;
|
|
xcb_screen_t* screen = nullptr;
|
|
|
|
struct WindowConnection {
|
|
xcb_connection_t* connection;
|
|
xcb_window_t window;
|
|
};
|
|
|
|
std::vector<WindowConnection> window_connections;
|
|
|
|
xcb_intern_atom_reply_t *atom_wm_delete_window;
|
|
|
|
static std::map<InputButton, int> inputToKeyCode = { {
|
|
{InputButton::A, 38},
|
|
{InputButton::W, 25},
|
|
{InputButton::S, 39},
|
|
{InputButton::D, 40},
|
|
{InputButton::Q, 24}
|
|
}};
|
|
|
|
/*
|
|
* Platform functions"
|
|
*/
|
|
|
|
const char* platform::get_name() {
|
|
return "Linux";
|
|
}
|
|
|
|
static inline xcb_intern_atom_reply_t* intern_atom_helper(xcb_connection_t *conn, bool only_if_exists, const char *str)
|
|
{
|
|
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(conn, only_if_exists, strlen(str), str);
|
|
return xcb_intern_atom_reply(conn, cookie, NULL);
|
|
}
|
|
|
|
int platform::open_window(const std::string_view title, const int x, const int y, const int width, const int height, const WindowFlags flags) {
|
|
auto& win = window_connections.emplace_back();
|
|
win.connection = connection;
|
|
|
|
uint32_t mask;
|
|
uint32_t values[32];
|
|
|
|
xcb_void_cookie_t cookie;
|
|
|
|
mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
|
|
values[0] = screen->black_pixel;
|
|
values[1] =
|
|
XCB_EVENT_MASK_KEY_RELEASE |
|
|
XCB_EVENT_MASK_KEY_PRESS |
|
|
XCB_EVENT_MASK_EXPOSURE |
|
|
XCB_EVENT_MASK_STRUCTURE_NOTIFY |
|
|
XCB_EVENT_MASK_POINTER_MOTION |
|
|
XCB_EVENT_MASK_BUTTON_PRESS |
|
|
XCB_EVENT_MASK_BUTTON_RELEASE;
|
|
|
|
win.window = xcb_generate_id(connection);
|
|
cookie = xcb_create_window(win.connection,
|
|
XCB_COPY_FROM_PARENT, win.window, screen->root,
|
|
x, y, width, height,
|
|
0,
|
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
|
screen->root_visual,
|
|
mask, values);
|
|
|
|
|
|
/* Magic code that will send notification when window is destroyed */
|
|
xcb_intern_atom_reply_t* reply = intern_atom_helper(connection, true, "WM_PROTOCOLS");
|
|
atom_wm_delete_window = intern_atom_helper(connection, false, "WM_DELETE_WINDOW");
|
|
|
|
xcb_change_property(connection, XCB_PROP_MODE_REPLACE,
|
|
win.window, (*reply).atom, 4, 32, 1,
|
|
&(*atom_wm_delete_window).atom);
|
|
|
|
xcb_change_property(connection, XCB_PROP_MODE_REPLACE,
|
|
win.window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
|
|
title.size(), title.data());
|
|
|
|
xcb_map_window(connection, win.window);
|
|
xcb_flush(connection);
|
|
|
|
engine->add_window((void*)&win, 0, width, height);
|
|
app->initialize_render();
|
|
|
|
return window_connections.size() - 1;
|
|
}
|
|
|
|
void platform::close_window(const int index) {
|
|
}
|
|
|
|
void platform::force_quit() {
|
|
}
|
|
|
|
float platform::get_window_dpi(const int index) {
|
|
return 1.0;
|
|
}
|
|
|
|
float platform::get_monitor_dpi() {
|
|
return 1.0;
|
|
}
|
|
|
|
platform::Rect platform::get_monitor_resolution() {
|
|
}
|
|
|
|
platform::Rect platform::get_monitor_work_area() {
|
|
}
|
|
|
|
std::tuple<int, int> platform::get_window_position(const int index) {
|
|
}
|
|
|
|
std::tuple<int, int> platform::get_window_size(const int index) {
|
|
}
|
|
|
|
std::tuple<int, int> platform::get_window_drawable_size(const int index) {
|
|
}
|
|
bool platform::is_window_focused(const int index) {
|
|
}
|
|
|
|
void platform::set_window_focused(const int index) {
|
|
}
|
|
|
|
void platform::set_window_position(const int index, const int x, const int y) {
|
|
}
|
|
|
|
void platform::set_window_size(const int index, const int w, const int h) {
|
|
}
|
|
|
|
void platform::set_window_title(const int index, const std::string_view title) {
|
|
xcb_change_property(connection, XCB_PROP_MODE_REPLACE,
|
|
window_connections[index].window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
|
|
title.size(), title.data());
|
|
}
|
|
|
|
bool platform::get_key_down(const InputButton key) {
|
|
int keycode = inputToKeyCode[key];
|
|
|
|
char keys[32];
|
|
XQueryKeymap(dpy, keys);
|
|
|
|
return keys[keycode/8]&(0x1<<(keycode%8));
|
|
}
|
|
|
|
int platform::get_keycode(const InputButton key) {
|
|
return inputToKeyCode[key];
|
|
}
|
|
|
|
std::tuple<int, int> platform::get_cursor_position() {
|
|
return {mouse_x, mouse_y};
|
|
}
|
|
|
|
std::tuple<int, int> platform::get_screen_cursor_position() {
|
|
return {mouse_x, mouse_y};
|
|
}
|
|
|
|
bool platform::get_mouse_button_down(const int button) {
|
|
return mouse_down[button];
|
|
}
|
|
|
|
std::tuple<float, float> platform::get_wheel_delta() {
|
|
}
|
|
|
|
std::tuple<float, float> platform::get_right_stick_position() {
|
|
}
|
|
|
|
std::tuple<float, float> platform::get_left_stick_position() {
|
|
}
|
|
|
|
void platform::capture_mouse(const bool capture) {
|
|
}
|
|
|
|
void platform::open_dialog(const bool existing, std::function<void(std::string)> returnFunction, bool openDirectory) {
|
|
}
|
|
|
|
void platform::save_dialog(std::function<void(std::string)> returnFunction) {
|
|
}
|
|
|
|
char* platform::translate_keycode(const unsigned int keycode) {
|
|
char* array = new char[2];
|
|
|
|
XKeyEvent event;
|
|
memset(&event, 0, sizeof(event));
|
|
event.type = 2;
|
|
event.display = dpy;
|
|
event.keycode = keycode;
|
|
int count = XLookupString(&event, array, 1, nullptr, 0);
|
|
|
|
array[1] = '\0';
|
|
|
|
return array;
|
|
}
|
|
|
|
int stdout_copy;
|
|
int stderr_copy;
|
|
|
|
void platform::mute_output() {
|
|
stdout_copy = dup(STDOUT_FILENO);
|
|
stderr_copy = dup(STDERR_FILENO);
|
|
|
|
freopen("/dev/null", "a", stdout);
|
|
freopen("/dev/null", "a", stderr);
|
|
}
|
|
|
|
void platform::unmute_output() {
|
|
dup2(stdout_copy, STDOUT_FILENO);
|
|
dup2(stderr_copy, STDERR_FILENO);
|
|
|
|
close(stdout_copy);
|
|
close(stderr_copy);
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
dpy = XOpenDisplay(nullptr);
|
|
|
|
const xcb_setup_t *setup;
|
|
xcb_screen_iterator_t iter;
|
|
int scr;
|
|
|
|
connection = xcb_connect(NULL, &scr);
|
|
|
|
setup = xcb_get_setup(connection);
|
|
iter = xcb_setup_roots_iterator(setup);
|
|
while (scr-- > 0)
|
|
xcb_screen_next(&iter);
|
|
screen = iter.data;
|
|
|
|
engine = new Engine(argc, argv);
|
|
|
|
app = new @APP_CLASS@();
|
|
engine->set_app(app);
|
|
|
|
GFXCreateInfo info = {};
|
|
|
|
interface = new GFXVulkan();
|
|
if(interface->initialize(info)) {
|
|
engine->set_gfx(interface);
|
|
} else {
|
|
return -1;
|
|
}
|
|
|
|
app_main(engine);
|
|
|
|
while(1) {
|
|
xcb_generic_event_t* event = nullptr;
|
|
|
|
while((event = xcb_poll_for_event (connection))) {
|
|
switch(event->response_type & 0x7f) {
|
|
case XCB_CLIENT_MESSAGE:
|
|
{
|
|
if ((*(xcb_client_message_event_t*)event).data.data32[0] ==
|
|
(*atom_wm_delete_window).atom) {
|
|
engine->quit();
|
|
}
|
|
}
|
|
break;
|
|
case XCB_MOTION_NOTIFY:
|
|
{
|
|
auto ev = (xcb_motion_notify_event_t *)event;
|
|
|
|
engine->process_mouse_move(ev->event_x, ev->event_y);
|
|
|
|
mouse_x = ev->event_x;
|
|
mouse_y = ev->event_y;
|
|
}
|
|
break;
|
|
case XCB_BUTTON_PRESS:
|
|
{
|
|
xcb_button_press_event_t *press = (xcb_button_press_event_t *)event;
|
|
int index = 0;
|
|
if(press->detail == 3)
|
|
index = 1;
|
|
|
|
engine->process_mouse(index, press->event_x, press->event_y);
|
|
|
|
mouse_down[index] = true;
|
|
|
|
mouse_x = press->event_x;
|
|
mouse_y = press->event_y;
|
|
}
|
|
break;
|
|
case XCB_BUTTON_RELEASE:
|
|
{
|
|
xcb_button_press_event_t *press = (xcb_button_press_event_t *)event;
|
|
int index = 0;
|
|
if(press->detail == 3)
|
|
index = 1;
|
|
|
|
engine->process_mouse_released(index);
|
|
|
|
mouse_down[index] = false;
|
|
}
|
|
break;
|
|
case XCB_CONFIGURE_NOTIFY:
|
|
{
|
|
const xcb_configure_notify_event_t *cfgEvent = (const xcb_configure_notify_event_t *)event;
|
|
|
|
engine->resize(0, cfgEvent->width, cfgEvent->height);
|
|
}
|
|
break;
|
|
case XCB_KEY_PRESS:
|
|
{
|
|
const xcb_key_release_event_t *keyEvent = (const xcb_key_release_event_t *)event;
|
|
|
|
engine->process_key(keyEvent->detail);
|
|
}
|
|
break;
|
|
case XCB_KEY_RELEASE:
|
|
{
|
|
const xcb_key_release_event_t *keyEvent = (const xcb_key_release_event_t *)event;
|
|
|
|
engine->process_key_up(keyEvent->detail);
|
|
}
|
|
break;
|
|
}
|
|
|
|
free(event);
|
|
}
|
|
|
|
if(engine->is_quitting())
|
|
break;
|
|
|
|
engine->update(1.0 / 60.0);
|
|
engine->begin_frame();
|
|
engine->render(0);
|
|
}
|
|
|
|
return 0;
|
|
}
|