Seperate engine and app logic, and moved editor to different build target/source file
parent
60f518580a
commit
ff46b21e11
@ -0,0 +1,87 @@
|
||||
#ifndef ENGINE_H
|
||||
#define ENGINE_H
|
||||
|
||||
#include "GLFW/glfw3.h"
|
||||
#include "gpu.h"
|
||||
#include "ui.h"
|
||||
#include "hex.h"
|
||||
|
||||
typedef struct ClientContextStruct ClientContext;
|
||||
|
||||
typedef bool (*app_text_callback)(
|
||||
ClientContext* context,
|
||||
unsigned int codepoint);
|
||||
|
||||
typedef bool (*app_key_callback)(
|
||||
ClientContext* context,
|
||||
int key,
|
||||
int action,
|
||||
int mods);
|
||||
|
||||
typedef bool (*app_button_callback)(
|
||||
ClientContext* context,
|
||||
float x,
|
||||
float y,
|
||||
int button,
|
||||
int action,
|
||||
int mods);
|
||||
|
||||
typedef bool (*app_scroll_callback)(
|
||||
ClientContext* context,
|
||||
double x,
|
||||
double y);
|
||||
|
||||
typedef bool (*app_cursor_callback)(
|
||||
ClientContext* context,
|
||||
float x,
|
||||
float y);
|
||||
|
||||
typedef void (*app_frame_function)(
|
||||
ClientContext* context);
|
||||
|
||||
typedef void (*app_startup_function)(
|
||||
ClientContext* context);
|
||||
|
||||
struct ClientContextStruct {
|
||||
GLFWwindow* window;
|
||||
|
||||
RenderContext render;
|
||||
UIContext ui;
|
||||
HexContext hex;
|
||||
|
||||
vec3 position;
|
||||
vec3 velocity;
|
||||
|
||||
vec2 rotation;
|
||||
int32_t key_spin[2];
|
||||
vec2 cur_spin;
|
||||
|
||||
double distance;
|
||||
int32_t zoom;
|
||||
|
||||
bool camera_mode;
|
||||
float key_spin_speed;
|
||||
float cur_spin_speed;
|
||||
float zoom_speed;
|
||||
float move_speed;
|
||||
|
||||
void* app_data;
|
||||
app_frame_function app_frame;
|
||||
app_text_callback app_text;
|
||||
app_key_callback app_key;
|
||||
app_button_callback app_button;
|
||||
app_scroll_callback app_scroll;
|
||||
app_cursor_callback app_cursor;
|
||||
};
|
||||
|
||||
int run_app(
|
||||
void* app_data,
|
||||
app_startup_function app_startup,
|
||||
app_frame_function app_frame,
|
||||
app_text_callback app_text,
|
||||
app_key_callback app_key,
|
||||
app_button_callback app_button,
|
||||
app_scroll_callback app_scroll,
|
||||
app_cursor_callback app_cursor);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,432 @@
|
||||
#include "engine.h"
|
||||
#include "gpu.h"
|
||||
#include "draw.h"
|
||||
|
||||
void text_callback(GLFWwindow* window, unsigned int codepoint) {
|
||||
ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window);
|
||||
if(context->ui.active_callbacks != NULL
|
||||
&& context->ui.active_callbacks->text != NULL
|
||||
&& context->ui.active_callbacks->text(
|
||||
context->ui.active_callbacks->data,
|
||||
&context->ui,
|
||||
&context->render,
|
||||
codepoint)) return;
|
||||
|
||||
if(context->app_text != NULL && context->app_text(context, codepoint)) return;
|
||||
}
|
||||
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||
(void)scancode;
|
||||
(void)mods;
|
||||
|
||||
ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window);
|
||||
|
||||
if(context->ui.active_callbacks != NULL
|
||||
&& context->ui.active_callbacks->key != NULL
|
||||
&& context->ui.active_callbacks->key(
|
||||
context->ui.active_callbacks->data,
|
||||
&context->ui,
|
||||
&context->render,
|
||||
key, action, mods)) return;
|
||||
|
||||
if(context->app_key != NULL && context->app_key(context, key, action, mods)) return;
|
||||
|
||||
switch(key) {
|
||||
case GLFW_KEY_A:
|
||||
if(action == GLFW_PRESS) {
|
||||
context->key_spin[0] -= 1;
|
||||
} else if(action == GLFW_RELEASE) {
|
||||
context->key_spin[0] += 1;
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_D:
|
||||
if(action == GLFW_PRESS) {
|
||||
context->key_spin[0] += 1;
|
||||
} else if(action == GLFW_RELEASE) {
|
||||
context->key_spin[0] -= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case GLFW_KEY_W:
|
||||
if(action == GLFW_PRESS) {
|
||||
context->key_spin[1] += 1;
|
||||
} else if(action == GLFW_RELEASE) {
|
||||
context->key_spin[1] -= 1;
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_S:
|
||||
if(action == GLFW_PRESS) {
|
||||
context->key_spin[1] -= 1;
|
||||
} else if(action == GLFW_RELEASE) {
|
||||
context->key_spin[1] += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case GLFW_KEY_UP:
|
||||
if(action == GLFW_PRESS) {
|
||||
context->velocity[2] += 1;
|
||||
} else if(action == GLFW_RELEASE) {
|
||||
context->velocity[2] -= 1;
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_DOWN:
|
||||
if(action == GLFW_PRESS) {
|
||||
context->velocity[2] -= 1;
|
||||
} else if(action == GLFW_RELEASE) {
|
||||
context->velocity[2] += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case GLFW_KEY_LEFT:
|
||||
if(action == GLFW_PRESS) {
|
||||
context->velocity[0] -= 1;
|
||||
} else if(action == GLFW_RELEASE) {
|
||||
context->velocity[0] += 1;
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_RIGHT:
|
||||
if(action == GLFW_PRESS) {
|
||||
context->velocity[0] += 1;
|
||||
} else if(action == GLFW_RELEASE) {
|
||||
context->velocity[0] -= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case GLFW_KEY_LEFT_SHIFT:
|
||||
if(action == GLFW_PRESS) {
|
||||
context->velocity[1] -= 1;
|
||||
} else if(action == GLFW_RELEASE) {
|
||||
context->velocity[1] += 1;
|
||||
}
|
||||
break;
|
||||
case GLFW_KEY_SPACE:
|
||||
if(action == GLFW_PRESS) {
|
||||
context->velocity[1] += 1;
|
||||
} else if(action == GLFW_RELEASE) {
|
||||
context->velocity[1] -= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void button_callback(GLFWwindow* window, int button, int action, int mods) {
|
||||
double cursor[2];
|
||||
uint32_t container;
|
||||
uint32_t layer;
|
||||
uint32_t element;
|
||||
vec2 position;
|
||||
|
||||
ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window);
|
||||
|
||||
glfwGetCursorPos(window, &cursor[0], &cursor[1]);
|
||||
|
||||
if(context->ui.active_callbacks != NULL && context->ui.active_callbacks->button != NULL) {
|
||||
Container* container_ptr = context_container(context->ui.active_container, &context->ui);
|
||||
GPUDrawable* drawable_ptr = &container_ptr->layers[context->ui.active_layer].drawables_buffer[context->ui.active_element];
|
||||
vec2 element_pos = {
|
||||
drawable_ptr->pos[0] + container_ptr->data.offset[0],
|
||||
drawable_ptr->pos[1] + container_ptr->data.offset[1],
|
||||
};
|
||||
anchor_offset(&context->render, container_ptr, element_pos);
|
||||
vec2 element_size = {
|
||||
drawable_ptr->size[0],
|
||||
drawable_ptr->size[1],
|
||||
};
|
||||
|
||||
vec2 point = {
|
||||
(cursor[0] - element_pos[0])/element_size[0],
|
||||
(cursor[1] - element_pos[1])/element_size[1],
|
||||
};
|
||||
|
||||
if((point[0] <= 1 && point[0] >= 0 && point[1] <= 1 && point[1] >= 0) || action == GLFW_RELEASE) {
|
||||
context->ui.active_callbacks->button(
|
||||
context->ui.active_callbacks->data,
|
||||
&context->ui,
|
||||
&context->render,
|
||||
point[0],
|
||||
point[1],
|
||||
button,
|
||||
action,
|
||||
mods);
|
||||
return;
|
||||
} else {
|
||||
clear_active_element(&context->ui, &context->render);
|
||||
}
|
||||
}
|
||||
|
||||
if(context->app_button != NULL && context->app_button(context, cursor[0], cursor[1], button, action, mods)) return;
|
||||
|
||||
if(ui_intersect(cursor, &context->render, &context->ui, UI_EVENT_BUTTON, &container, &layer, &element, position)) {
|
||||
Container* container_ptr = context_container(container, &context->ui);
|
||||
for(uint32_t c = 0; c < container_ptr->callback_count; c++) {
|
||||
if(container_ptr->callbacks[c].element == element) {
|
||||
if(container_ptr->callbacks[c].button != NULL) {
|
||||
if(container_ptr->callbacks[c].button(
|
||||
container_ptr->callbacks[c].data,
|
||||
&context->ui,
|
||||
&context->render,
|
||||
position[0],
|
||||
position[1],
|
||||
button,
|
||||
action,
|
||||
mods)) return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_hex_click(cursor, &context->hex, &context->render);
|
||||
if(button == GLFW_MOUSE_BUTTON_MIDDLE) {
|
||||
if(action == GLFW_PRESS) {
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
context->camera_mode = true;
|
||||
} else {
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
context->camera_mode = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
|
||||
(void)xoffset;
|
||||
uint32_t container;
|
||||
uint32_t layer;
|
||||
uint32_t element;
|
||||
vec2 position;
|
||||
|
||||
ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window);
|
||||
if(context->ui.active_callbacks != NULL
|
||||
&& context->ui.active_callbacks->scroll != NULL
|
||||
&& context->ui.active_callbacks->scroll(
|
||||
context->ui.active_callbacks->data,
|
||||
&context->ui,
|
||||
&context->render,
|
||||
xoffset, yoffset)) return;
|
||||
|
||||
if(context->app_scroll != NULL && context->app_scroll(context, xoffset, yoffset)) return;
|
||||
|
||||
if(ui_intersect(
|
||||
context->ui.cursor,
|
||||
&context->render,
|
||||
&context->ui,
|
||||
UI_EVENT_SCROLL,
|
||||
&container,
|
||||
&layer,
|
||||
&element,
|
||||
position)) {
|
||||
Container* container_ptr = context_container(container, &context->ui);
|
||||
for(uint32_t c = 0; c < container_ptr->callback_count; c++) {
|
||||
if(container_ptr->callbacks[c].element == element) {
|
||||
if(container_ptr->callbacks[c].scroll != NULL) {
|
||||
container_ptr->callbacks[c].scroll(
|
||||
container_ptr->callbacks[c].data,
|
||||
&context->ui,
|
||||
&context->render,
|
||||
xoffset,
|
||||
yoffset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context->zoom = -yoffset;
|
||||
}
|
||||
}
|
||||
|
||||
void cursor_callback(GLFWwindow* window, double xpos, double ypos) {
|
||||
ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window);
|
||||
uint32_t container;
|
||||
uint32_t element;
|
||||
uint32_t layer;
|
||||
vec2 position;
|
||||
vec2 last_cursor = {
|
||||
context->ui.cursor[0],
|
||||
context->ui.cursor[1],
|
||||
};
|
||||
|
||||
context->ui.cursor[0] = xpos;
|
||||
context->ui.cursor[1] = ypos;
|
||||
|
||||
if(context->camera_mode == true) {
|
||||
context->cur_spin[0] = (xpos - last_cursor[0])/context->render.swapchain_extent.width*-100;
|
||||
context->cur_spin[1] = (ypos - last_cursor[1])/context->render.swapchain_extent.height*100;
|
||||
} else {
|
||||
if(context->ui.active_callbacks != NULL && context->ui.active_callbacks->cursor != NULL) {
|
||||
Container* container_ptr = context_container(context->ui.active_container, &context->ui);
|
||||
GPUDrawable* drawable_ptr = &container_ptr->layers[context->ui.active_layer].drawables_buffer[context->ui.active_element];
|
||||
vec2 element_pos = {
|
||||
drawable_ptr->pos[0] + container_ptr->data.offset[0],
|
||||
drawable_ptr->pos[1] + container_ptr->data.offset[1],
|
||||
};
|
||||
anchor_offset(&context->render, container_ptr, element_pos);
|
||||
vec2 element_size = {
|
||||
drawable_ptr->size[0],
|
||||
drawable_ptr->size[1],
|
||||
};
|
||||
if(context->ui.active_callbacks->cursor(
|
||||
context->ui.active_callbacks->data,
|
||||
&context->ui,
|
||||
&context->render,
|
||||
(context->ui.cursor[0] - element_pos[0])/element_size[0],
|
||||
(context->ui.cursor[1] - element_pos[1])/element_size[1])) return;
|
||||
}
|
||||
|
||||
if(context->app_cursor != NULL && context->app_cursor(context, xpos, ypos)) return;
|
||||
|
||||
if(ui_intersect(context->ui.cursor, &context->render, &context->ui, UI_EVENT_CURSOR, &container, &layer, &element, position)) {
|
||||
Container* container_ptr = context_container(container, &context->ui);
|
||||
for(uint32_t c = 0; c < container_ptr->callback_count; c++) {
|
||||
if(container_ptr->callbacks[c].element == element) {
|
||||
if(container_ptr->callbacks[c].cursor != NULL) {
|
||||
container_ptr->callbacks[c].cursor(
|
||||
container_ptr->callbacks[c].data,
|
||||
&context->ui,
|
||||
&context->render,
|
||||
position[0],
|
||||
position[1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
update_hex_hover(context->ui.cursor, &context->hex, &context->render);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int app_main(ClientContext* context) {
|
||||
VkResult result;
|
||||
|
||||
//
|
||||
double last_frame_time = 0;
|
||||
while(glfwWindowShouldClose(context->window) == 0) {
|
||||
double frame_time = glfwGetTime();
|
||||
double delta_time = (frame_time - last_frame_time);
|
||||
|
||||
// Reset callback variables
|
||||
context->zoom = 0;
|
||||
context->cur_spin[0] = 0;
|
||||
context->cur_spin[1] = 0;
|
||||
|
||||
glfwPollEvents();
|
||||
if(context->app_frame != NULL) context->app_frame(context);
|
||||
|
||||
if((context->key_spin[0] != 0 || context->key_spin[1] != 0 ||
|
||||
context->velocity[0] != 0 || context->velocity[1] != 0 || context->velocity[2] != 0 ||
|
||||
context->zoom != 0 ||
|
||||
context->cur_spin[0] != 0 || context->cur_spin[1] != 0 ||
|
||||
context->render.framebuffer_recreated == true)) {
|
||||
|
||||
|
||||
if(context->render.framebuffer_recreated == true) {
|
||||
context->render.framebuffer_recreated = false;
|
||||
VK_RESULT(update_hex_proj(&context->render, &context->hex));
|
||||
VK_RESULT(update_ui_context_resolution(&context->ui, &context->render));
|
||||
}
|
||||
|
||||
context->rotation[0] += (float)context->key_spin[0]*delta_time*context->key_spin_speed;
|
||||
context->rotation[0] += (float)context->cur_spin[0]*delta_time*context->cur_spin_speed;
|
||||
if(context->rotation[0] > 2*M_PI) {
|
||||
context->rotation[0] -= 2*M_PI;
|
||||
} else if(context->rotation[0] < 0) {
|
||||
context->rotation[0] += 2*M_PI;
|
||||
}
|
||||
|
||||
context->rotation[1] += (float)context->key_spin[1]*delta_time*context->key_spin_speed;
|
||||
context->rotation[1] += (float)context->cur_spin[1]*delta_time*context->cur_spin_speed;
|
||||
if(context->rotation[1] > (M_PI/2 - 0.1)) {
|
||||
context->rotation[1] = (M_PI/2 - 0.1);
|
||||
} else if(context->rotation[1] < 0) {
|
||||
context->rotation[1] = 0;
|
||||
}
|
||||
|
||||
context->position[0] += - context->velocity[2]*context->move_speed*cos(context->rotation[0])
|
||||
- context->velocity[0]*context->move_speed*sin(context->rotation[0]);
|
||||
|
||||
context->position[2] += context->velocity[0]*context->move_speed*cos(context->rotation[0])
|
||||
- context->velocity[2]*context->move_speed*sin(context->rotation[0]);
|
||||
|
||||
context->position[1] += context->velocity[1]*context->move_speed;
|
||||
|
||||
context->distance += context->zoom*delta_time*context->zoom_speed;
|
||||
if(context->distance < 1) {
|
||||
context->distance = 1;
|
||||
}
|
||||
|
||||
VK_RESULT(update_hex_view(
|
||||
context->position,
|
||||
context->rotation,
|
||||
context->distance,
|
||||
&context->render,
|
||||
&context->hex));
|
||||
}
|
||||
//
|
||||
|
||||
VkResult result = draw_frame(&context->render, &context->ui, &context->hex, frame_time);
|
||||
if(result != VK_SUCCESS) {
|
||||
fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result));
|
||||
glfwDestroyWindow(context->window);
|
||||
}
|
||||
|
||||
last_frame_time = frame_time;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int run_app(
|
||||
void* app_data,
|
||||
app_startup_function app_startup,
|
||||
app_frame_function app_frame,
|
||||
app_text_callback app_text,
|
||||
app_key_callback app_key,
|
||||
app_button_callback app_button,
|
||||
app_scroll_callback app_scroll,
|
||||
app_cursor_callback app_cursor) {
|
||||
ClientContext* context = malloc(sizeof(ClientContext));
|
||||
if(context == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(context, 0, sizeof(ClientContext));
|
||||
|
||||
context->window = init_window();
|
||||
|
||||
context->rotation[0] = 3*M_PI/2;
|
||||
context->rotation[1] = M_PI/4;
|
||||
context->distance = 25;
|
||||
context->key_spin_speed = 1.0;
|
||||
context->cur_spin_speed = 1.0;
|
||||
context->zoom_speed = 1.0;
|
||||
context->move_speed = 0.1;
|
||||
|
||||
memset(&context->render, 0, sizeof(RenderContext));
|
||||
memset(&context->ui, 0, sizeof(UIContext));
|
||||
memset(&context->hex, 0, sizeof(HexContext));
|
||||
|
||||
context->app_data = app_data;
|
||||
context->app_frame = app_frame;
|
||||
context->app_text = app_text;
|
||||
context->app_key = app_key;
|
||||
context->app_button = app_button;
|
||||
context->app_scroll = app_scroll;
|
||||
context->app_cursor = app_cursor;
|
||||
|
||||
glfwSetWindowUserPointer(context->window, context);
|
||||
glfwSetKeyCallback(context->window, key_callback);
|
||||
glfwSetMouseButtonCallback(context->window, button_callback);
|
||||
glfwSetScrollCallback(context->window, scroll_callback);
|
||||
glfwSetCursorPosCallback(context->window, cursor_callback);
|
||||
glfwSetCharCallback(context->window, text_callback);
|
||||
|
||||
if(init_vulkan(context->window, &context->render) != VK_SUCCESS) return -2;
|
||||
|
||||
// TODO: make # of fonts/textures/containers scaling, recreate GPU buffers as necessary
|
||||
if(create_ui_context(10, 10, 10, &context->render, &context->ui) != VK_SUCCESS) return -3;
|
||||
if(create_hex_context(&context->render, &context->hex) != VK_SUCCESS) return -4;
|
||||
|
||||
if(app_startup != NULL) app_startup(context);
|
||||
|
||||
return app_main(context);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue