|
|
|
@ -1,3 +1,4 @@
|
|
|
|
|
#include "GLFW/glfw3.h"
|
|
|
|
|
#include "ui.h"
|
|
|
|
|
#include "gpu.h"
|
|
|
|
|
#include "draw.h"
|
|
|
|
@ -6,6 +7,14 @@
|
|
|
|
|
#include "vk_mem_alloc.h"
|
|
|
|
|
#include "vulkan/vk_enum_string_helper.h"
|
|
|
|
|
#include "vulkan/vulkan_core.h"
|
|
|
|
|
#include "pthread.h"
|
|
|
|
|
#include "stdatomic.h"
|
|
|
|
|
|
|
|
|
|
typedef struct ClientContextStruct {
|
|
|
|
|
GLFWwindow* window;
|
|
|
|
|
RenderContext render;
|
|
|
|
|
UIContext ui;
|
|
|
|
|
} ClientContext;
|
|
|
|
|
|
|
|
|
|
VkResult test_ui(RenderContext* render, UIContext* ui) {
|
|
|
|
|
VkResult result;
|
|
|
|
@ -35,21 +44,12 @@ VkResult test_ui(RenderContext* render, UIContext* ui) {
|
|
|
|
|
.length = strlen("Example Text"),
|
|
|
|
|
.font = 2,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.pos = {0, 128},
|
|
|
|
|
.size = 32,
|
|
|
|
|
.color = {1.0, 1.0, 1.0, 1.0},
|
|
|
|
|
.offset = 3*strlen("Example Text"),
|
|
|
|
|
.length = strlen("Example Text"),
|
|
|
|
|
.font = 3,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
uint32_t context_codes[256];
|
|
|
|
|
map_string("Example Text", context_codes, 0, 0, ui);
|
|
|
|
|
map_string("Example Text", context_codes, strlen("Example Text"), 1, ui);
|
|
|
|
|
map_string("Example Text", context_codes, 2*strlen("Example Text"), 2, ui);
|
|
|
|
|
map_string("Example Text", context_codes, 3*strlen("Example Text"), 3, ui);
|
|
|
|
|
|
|
|
|
|
LayerInput context_layers[] = {
|
|
|
|
|
{
|
|
|
|
@ -151,49 +151,56 @@ VkResult test_ui(RenderContext* render, UIContext* ui) {
|
|
|
|
|
VK_RESULT(create_container(&inventory_info, render, ui));
|
|
|
|
|
VK_RESULT(create_container(&chat_info, render, ui));
|
|
|
|
|
|
|
|
|
|
VK_RESULT(record_draw_commands(render, ui));
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult render_thread(GLFWwindow* window, RenderContext* render) {
|
|
|
|
|
|
|
|
|
|
VkResult result;
|
|
|
|
|
// Threads:
|
|
|
|
|
// 1. render
|
|
|
|
|
// - Submits the draw buffer to the GPU as soon as it can
|
|
|
|
|
// 2. network
|
|
|
|
|
// - Handles packets to/from the network to/from the main thread
|
|
|
|
|
// 3. main
|
|
|
|
|
// - updates the data in the GPU that's being drawn from
|
|
|
|
|
// - updates the data in the GPU from network requests
|
|
|
|
|
//
|
|
|
|
|
// Data:
|
|
|
|
|
// Render thread reads Render and UI context
|
|
|
|
|
// Main thread reads and writes UI context
|
|
|
|
|
|
|
|
|
|
void* render_thread(void* data) {
|
|
|
|
|
ClientContext* context = (ClientContext*)data;
|
|
|
|
|
|
|
|
|
|
double last_frame_time = glfwGetTime();
|
|
|
|
|
while(glfwWindowShouldClose(window) == 0) {
|
|
|
|
|
glfwPollEvents();
|
|
|
|
|
|
|
|
|
|
while(glfwWindowShouldClose(context->window) == 0) {
|
|
|
|
|
double frame_time = glfwGetTime();
|
|
|
|
|
double delta_time = frame_time - last_frame_time;
|
|
|
|
|
(void)delta_time;
|
|
|
|
|
result = draw_frame(render, frame_time);
|
|
|
|
|
|
|
|
|
|
VkResult result = draw_frame(&context->render, &context->ui, frame_time);
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result));
|
|
|
|
|
return result;
|
|
|
|
|
glfwDestroyWindow(context->window);
|
|
|
|
|
}
|
|
|
|
|
last_frame_time = frame_time;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef enum ClientAuthStateEnum {
|
|
|
|
|
AUTH_SAVED,
|
|
|
|
|
AUTH_CREDENTIALS,
|
|
|
|
|
AUTH_ATTEMPT,
|
|
|
|
|
AUTH_ERROR,
|
|
|
|
|
AUTH_SUCCESS,
|
|
|
|
|
} ClientAuthState;
|
|
|
|
|
void* network_thread(void* data) {
|
|
|
|
|
ClientContext* context = (ClientContext*)data;
|
|
|
|
|
(void)context;
|
|
|
|
|
|
|
|
|
|
typedef struct ClientStateStruct {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} ClientState;
|
|
|
|
|
int main_thread(void* data) {
|
|
|
|
|
ClientContext* context = (ClientContext*)data;
|
|
|
|
|
|
|
|
|
|
int logic_thread() {
|
|
|
|
|
return 0;
|
|
|
|
|
while(glfwWindowShouldClose(context->window) == 0) {
|
|
|
|
|
glfwPollEvents();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int network_thread() {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -206,7 +213,10 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
|
|
|
|
|
ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window);
|
|
|
|
|
|
|
|
|
|
(void)mods;
|
|
|
|
|
(void)context;
|
|
|
|
|
switch(button) {
|
|
|
|
|
// Handle camera hover
|
|
|
|
|
case GLFW_MOUSE_BUTTON_MIDDLE:
|
|
|
|
@ -218,6 +228,10 @@ void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
|
|
|
|
|
break;
|
|
|
|
|
case GLFW_MOUSE_BUTTON_LEFT:
|
|
|
|
|
if(action == GLFW_PRESS) {
|
|
|
|
|
// NOTE: this logic is the same as it would be for right-click(just with different outcomes), so dont repeat yourself
|
|
|
|
|
// 1. Search through the UI context for the first element that the contains the mouse point
|
|
|
|
|
// 2. If no UI element intersection, cast a ray through the world scene to find the "clicked entity"
|
|
|
|
|
// 3. Based on what was clicked, start the mouse click animation at the target area
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case GLFW_MOUSE_BUTTON_RIGHT:
|
|
|
|
@ -240,35 +254,61 @@ void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
|
GLFWwindow* window = init_window();
|
|
|
|
|
if(window == NULL) {
|
|
|
|
|
ClientContext context = {};
|
|
|
|
|
context.window = init_window();
|
|
|
|
|
if(context.window == NULL) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glfwSetKeyCallback(window, key_callback);
|
|
|
|
|
glfwSetMouseButtonCallback(window, mouse_button_callback);
|
|
|
|
|
glfwSetScrollCallback(window, scroll_callback);
|
|
|
|
|
glfwSetCursorPosCallback(window, cursor_pos_callback);
|
|
|
|
|
glfwSetWindowUserPointer(context.window, &context);
|
|
|
|
|
glfwSetKeyCallback(context.window, key_callback);
|
|
|
|
|
glfwSetMouseButtonCallback(context.window, mouse_button_callback);
|
|
|
|
|
glfwSetScrollCallback(context.window, scroll_callback);
|
|
|
|
|
glfwSetCursorPosCallback(context.window, cursor_pos_callback);
|
|
|
|
|
|
|
|
|
|
RenderContext render = {};
|
|
|
|
|
UIContext ui = {};
|
|
|
|
|
|
|
|
|
|
int error;
|
|
|
|
|
VkResult result;
|
|
|
|
|
VK_RESULT(init_vulkan(window, &render));
|
|
|
|
|
VK_RESULT(init_vulkan(context.window, &context.render));
|
|
|
|
|
|
|
|
|
|
// TODO: make # of fonts/textures/containers scaling, recreate GPU buffers as necessary
|
|
|
|
|
VK_RESULT(create_ui_context(10, 10, 10, &render, &ui));
|
|
|
|
|
VK_RESULT(create_ui_context(10, 10, 10, &context.render, &context.ui));
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////
|
|
|
|
|
/// Test Code
|
|
|
|
|
/// Test UI Code
|
|
|
|
|
//////////////////////////////////
|
|
|
|
|
|
|
|
|
|
VK_RESULT(test_ui(&render, &ui));
|
|
|
|
|
VK_RESULT(test_ui(&context.render, &context.ui));
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////
|
|
|
|
|
|
|
|
|
|
if(render_thread(window, &render) != VK_SUCCESS) {
|
|
|
|
|
return 3;
|
|
|
|
|
// Start threads
|
|
|
|
|
pthread_t render_thread_handle;
|
|
|
|
|
pthread_t network_thread_handle;
|
|
|
|
|
|
|
|
|
|
error = pthread_create(&render_thread_handle, NULL, &render_thread, &context);
|
|
|
|
|
if(error != 0) {
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
error = pthread_create(&network_thread_handle, NULL, &network_thread, &context);
|
|
|
|
|
if(error != 0) {
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
error = main_thread(&context);
|
|
|
|
|
if(error != 0) {
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
error = pthread_join(render_thread_handle, NULL);
|
|
|
|
|
if(error != 0) {
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
error = pthread_join(network_thread_handle, NULL);
|
|
|
|
|
if(error != 0) {
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|