Probably a lot idk, I was doing modal editing stuff

main
noah metz 2024-12-03 21:05:10 -07:00
parent 4379e6cd9b
commit 5e2e8f6d30
7 changed files with 345 additions and 614 deletions

@ -8,17 +8,17 @@
typedef struct ClientContextStruct ClientContext;
typedef bool (*app_text_callback)(
typedef void (*app_text_callback)(
ClientContext* context,
unsigned int codepoint);
typedef bool (*app_key_callback)(
typedef void (*app_key_callback)(
ClientContext* context,
int key,
int action,
int mods);
typedef bool (*app_button_callback)(
typedef void (*app_button_callback)(
ClientContext* context,
float x,
float y,
@ -26,12 +26,12 @@ typedef bool (*app_button_callback)(
int action,
int mods);
typedef bool (*app_scroll_callback)(
typedef void (*app_scroll_callback)(
ClientContext* context,
double x,
double y);
typedef bool (*app_cursor_callback)(
typedef void (*app_cursor_callback)(
ClientContext* context,
float x,
float y);
@ -53,15 +53,12 @@ struct ClientContextStruct {
vec3 velocity;
vec2 rotation;
int32_t key_spin[2];
vec2 cur_spin;
int32_t spin[2];
double distance;
int32_t zoom;
bool camera_mode;
float key_spin_speed;
float cur_spin_speed;
float spin_speed;
float zoom_speed;
float move_speed;

@ -150,6 +150,8 @@ typedef struct RenderContextStruct {
VkRenderPass render_pass;
VkCommandBuffer* swapchain_command_buffers;
uint64_t swapchain_command_buffer_record_id;
uint64_t* swapchain_command_buffer_record_ids;
FrameContext frame[MAX_FRAMES_IN_FLIGHT];

@ -266,11 +266,16 @@ VkResult load_texture(
UIContext* context,
uint32_t* index);
VkResult create_container(
VkResult load_container(
ContainerInput* container,
RenderContext* gpu,
UIContext* context);
VkResult unload_container(
uint32_t id,
RenderContext* gpu,
UIContext* context);
VkResult create_layer(
uint32_t index,
LayerInput* input,
@ -289,7 +294,7 @@ VkResult update_ui_context_resolution(
RenderContext* gpu);
VkResult update_ui_string(
char* string,
const char* string,
uint32_t container_id,
uint32_t layer_index,
uint32_t string_index,

@ -7,20 +7,54 @@
#include <math.h>
#include <stdlib.h>
#define COLOR_PICK_CONTAINER_ID 0x03
typedef struct EditorDataStruct {
uint32_t selected_region;
#define COLOR_PICK_CONTAINER_ID 0x02
#define MODE_STRING_CONTAINER_ID 0x01
uint32_t clicked_region;
uint32_t clicked_hex;
uint32_t clicked_vertex;
typedef enum EditorModeEnum {
MODE_NONE,
MODE_VERTEX,
MODE_NEIGHBOR,
MODE_HEX,
MODE_REGION,
MODE_MAX_ENUM,
} EditorMode;
const char* ModeStrings[] = {
"None",
"Vertex",
"Neighbor",
"Hex",
"Region",
};
typedef struct EditorDataStruct EditorData;
typedef void(*ModeKeyCallback)(EditorData* data, ClientContext* context, int action, int mods);
typedef struct ModeKeyStruct {
int key;
ModeKeyCallback logic;
} ModeKey;
struct EditorDataStruct {
EditorMode mode;
ModeKey* mode_keys[MODE_MAX_ENUM];
uint32_t mode_key_counts[MODE_MAX_ENUM];
uint32_t selected_max;
uint32_t selected_count;
uint32_t* selected_regions;
uint32_t* selected_hexes;
uint32_t* selected_vertices;
double current_hsv[3];
vec4 current;
vec4 saved[12];
char string[10];
int string_len;
} EditorData;
};
uint32_t hex_color(vec4 color) {
@ -475,6 +509,7 @@ SAVED_COLOR_BUTTON_CALLBACK(11);
.button = saved_color_button_callback_##n, \
}
// TODO: Make load from current state instead of having a default state
VkResult color_ui(ClientContext* context) {
GPUString strings[] = {
{
@ -691,7 +726,7 @@ VkResult color_ui(ClientContext* context) {
.callback_count = sizeof(callbacks)/sizeof(UICallbacks),
};
return create_container(&container, &context->render, &context->ui);
return load_container(&container, &context->render, &context->ui);
}
VkResult hex_info_ui(ClientContext* context) {
@ -789,495 +824,252 @@ VkResult hex_info_ui(ClientContext* context) {
.layer_count = 1,
};
return create_container(&container, &context->render, &context->ui);
return load_container(&container, &context->render, &context->ui);
}
VkResult region_info_ui(ClientContext* context) {
VkResult mode_string_ui(ClientContext* context) {
VkResult result;
GPUString strings[] = {
{
.pos = {0, 33},
.color = {1, 1, 1, 1},
.size = 32,
.offset = 0,
.length = 0,
.font = 0,
},
{
.pos = {0, 33 + 1*40},
.color = {1, 1, 1, 1},
.size = 32,
.offset = 11,
.length = 0,
.font = 0,
},
{
.pos = {0, 33 + 2*40},
.color = {1, 1, 1, 1},
.size = 32,
.offset = 18,
.length = 0,
.font = 0,
},
{
.pos = {0, 33 + 3*40},
.color = {1, 1, 1, 1},
.size = 32,
.offset = 25,
.length = 0,
.font = 0,
},
GPUString string = {
.pos = {0, 32},
.font = 0,
.size = 32,
.length = strlen(ModeStrings[MODE_NONE]),
.color = {1, 1, 1, 1},
};
GPUDrawable drawables[] = {
{
.pos = {0, 0},
.size = {225, 155},
.color = {{0.4, 0.4, 0.4, 0.8}, {0.4, 0.4, 0.4, 0.8}, {0.4, 0.4, 0.4, 0.8}, {0.4, 0.4, 0.4, 0.8}},
},
};
uint32_t codes[8];
VK_RESULT(map_string(ModeStrings[MODE_NONE], codes, 0, 0, &context->ui));
LayerInput layer = {
.strings = strings,
.num_strings = sizeof(strings)/sizeof(GPUString),
.max_strings = sizeof(strings)/sizeof(GPUString) + 4,
.max_codes = 100,
.drawables = drawables,
.num_drawables = sizeof(drawables)/sizeof(GPUDrawable),
.max_codes = 8,
.codes = codes,
.num_codes = strlen(ModeStrings[MODE_NONE]),
.num_strings = 1,
.strings = &string,
};
ContainerInput container = {
.id = 0x01,
.size = {225, 155},
.offset = {0, 0},
.anchor = ANCHOR_TOP_RIGHT,
.layers = &layer,
.id = MODE_STRING_CONTAINER_ID,
.layer_count = 1,
.layers = &layer,
.anchor = ANCHOR_TOP_LEFT,
.size = {160, 40},
};
return create_container(&container, &context->render, &context->ui);
return load_container(&container, &context->render, &context->ui);
}
VkResult update_region_info_ui(ClientContext* context) {
char temp[20];
VkResult result;
VkResult update_mode_string(ClientContext* context, EditorData* data) {
return update_ui_string(ModeStrings[data->mode], MODE_STRING_CONTAINER_ID, 0, 0, &context->ui, &context->render);
}
void editor_key_callback(ClientContext* context, int key, int action, int mods) {
EditorData* data = context->app_data;
for(uint32_t i = 0; i < data->mode_key_counts[data->mode]; i++) {
if(data->mode_keys[data->mode][i].key == key) {
data->mode_keys[data->mode][i].logic(data, context, action, mods);
return;
}
}
if(data->selected_region >= MAX_LOADED_REGIONS) {
snprintf(temp,
sizeof(temp),
"");
VK_RESULT(update_ui_string(temp, 0x01, 0, 0, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"");
VK_RESULT(update_ui_string(temp, 0x01, 0, 1, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"");
VK_RESULT(update_ui_string(temp, 0x01, 0, 2, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"");
VK_RESULT(update_ui_string(temp, 0x01, 0, 3, &context->ui, &context->render));
} else {
HexRegion* selected_region = context->hex.regions[data->selected_region];
snprintf(temp,
sizeof(temp),
"Region %4d", data->selected_region);
VK_RESULT(update_ui_string(temp, 0x01, 0, 0, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"Q: %4d", selected_region->data.position.q);
VK_RESULT(update_ui_string(temp, 0x01, 0, 1, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"R: %4d", selected_region->data.position.r);
VK_RESULT(update_ui_string(temp, 0x01, 0, 2, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"Y: %4d", selected_region->data.y);
VK_RESULT(update_ui_string(temp, 0x01, 0, 3, &context->ui, &context->render));
for(uint32_t i = 0; i < data->mode_key_counts[MODE_NONE]; i++) {
if(data->mode_keys[MODE_NONE][i].key == key) {
data->mode_keys[MODE_NONE][i].logic(data, context, action, mods);
return;
}
}
}
return VK_SUCCESS;
void spin_cam(ClientContext* context, int action, int mods, unsigned int axis, float amount) {
(void)mods;
if(action == GLFW_PRESS) context->spin[axis] += amount;
else if(action == GLFW_RELEASE) context->spin[axis] -= amount;
}
VkResult update_hex_info_ui(ClientContext* context) {
char temp[20];
VkResult result;
EditorData* data = context->app_data;
void spin_cam_left(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
spin_cam(context, action, mods, 0, -1);
}
void spin_cam_right(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
spin_cam(context, action, mods, 0, 1);
}
if(data->clicked_region >= MAX_LOADED_REGIONS) {
snprintf(
temp,
sizeof(temp),
"");
VK_RESULT(update_ui_string(temp, 0x02, 0, 0, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"");
VK_RESULT(update_ui_string(temp, 0x02, 0, 1, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"");
VK_RESULT(update_ui_string(temp, 0x02, 0, 2, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"");
VK_RESULT(update_ui_string(temp, 0x02, 0, 3, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"");
VK_RESULT(update_ui_string(temp, 0x02, 0, 4, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"");
VK_RESULT(update_ui_string(temp, 0x02, 0, 5, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"");
VK_RESULT(update_ui_string(temp, 0x02, 0, 6, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"");
VK_RESULT(update_ui_string(temp, 0x02, 0, 7, &context->ui, &context->render));
} else {
HexRegion* region = context->hex.regions[data->clicked_region];
GPUHex* hex = &region->data.hexes[data->clicked_hex];
snprintf(temp,
sizeof(temp),
"%d-%d",
data->clicked_region,
data->clicked_hex);
VK_RESULT(update_ui_string(temp, 0x02, 0, 0, &context->ui, &context->render));
HexCoord hex_world;
hex_qr(data->clicked_hex, &hex_world);
fprintf(stderr, "region: %d\n", data->clicked_region);
HexCoord region_coord = {region->data.position.q, region->data.position.r};
HexCoord region_world;
region_qr(region_coord, &region_world);
hex_add(region_world, &hex_world);
snprintf(
temp,
sizeof(temp),
"%d, %d, %d, %d",
hex_world.q,
hex_world.r,
region->data.y,
data->clicked_vertex);
VK_RESULT(update_ui_string(temp, 0x02, 0, 1, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"%02.02f %02.02f %02.02f",
hex->height[0], hex->height[1], hex->height[2]);
VK_RESULT(update_ui_string(temp, 0x02, 0, 2, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"%02.02f %02.02f %02.02f",
hex->height[3], hex->height[4], hex->height[5]);
VK_RESULT(update_ui_string(temp, 0x02, 0, 3, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"%08X",
hex->color[0]);
VK_RESULT(update_ui_string(temp, 0x02, 0, 4, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"%08X %08X",
hex->color[1], hex->color[2]);
VK_RESULT(update_ui_string(temp, 0x02, 0, 5, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"%08X %08X",
hex->color[3], hex->color[4]);
VK_RESULT(update_ui_string(temp, 0x02, 0, 6, &context->ui, &context->render));
snprintf(
temp,
sizeof(temp),
"%08X %08X",
hex->color[5], hex->color[6]);
VK_RESULT(update_ui_string(temp, 0x02, 0, 7, &context->ui, &context->render));
}
void spin_cam_up(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
spin_cam(context, action, mods, 1, 1);
}
return VK_SUCCESS;
void spin_cam_down(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
spin_cam(context, action, mods, 1, -1);
}
bool editor_key_callback(ClientContext* context, int key, int action, int mods) {
uint32_t start, next_region;
void move_cam(ClientContext* context, int action, int mods, unsigned int axis, float amount) {
(void)mods;
if(action == GLFW_PRESS) context->velocity[axis] += amount;
else if(action == GLFW_RELEASE) context->velocity[axis] -= amount;
}
if(action != GLFW_PRESS) return false;
void move_cam_up(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
move_cam(context, action, mods, 1, 1);
}
EditorData* data = context->app_data;
HexRegion* region = NULL;
switch(key) {
case GLFW_KEY_EQUAL:
data->selected_region = add_hex_region(context);
update_region_info_ui(context);
update_hex_info_ui(context);
break;
case GLFW_KEY_MINUS:
if(data->selected_region < MAX_LOADED_REGIONS) {
free_hex_region(data->selected_region, &context->hex, &context->render);
start = data->selected_region;
next_region = start;
do {
next_region -= 1;
if(next_region > MAX_LOADED_REGIONS) next_region = MAX_LOADED_REGIONS;
if(next_region != MAX_LOADED_REGIONS && context->hex.regions[next_region] != NULL) break;
} while(next_region != start);
if(next_region == start) {
data->selected_region = MAX_LOADED_REGIONS;
} else {
data->selected_region = next_region;
}
update_region_info_ui(context);
update_hex_info_ui(context);
}
break;
case GLFW_KEY_LEFT_BRACKET:
start = data->selected_region;
next_region = start;
do {
next_region -= 1;
if(next_region > MAX_LOADED_REGIONS) next_region = MAX_LOADED_REGIONS;
if(next_region != MAX_LOADED_REGIONS && context->hex.regions[next_region] != NULL) break;
} while(next_region != start);
data->selected_region = next_region;
update_region_info_ui(context);
break;
case GLFW_KEY_RIGHT_BRACKET:
start = data->selected_region;
next_region = start;
do {
next_region += 1;
if(next_region > MAX_LOADED_REGIONS) next_region = 0;
if(next_region != MAX_LOADED_REGIONS && context->hex.regions[next_region] != NULL) break;
} while(next_region != start);
data->selected_region = next_region;
update_region_info_ui(context);
break;
case GLFW_KEY_I:
if(data->selected_region < MAX_LOADED_REGIONS) {
context->hex.regions[data->selected_region]->data.position.q += 1;
add_transfer(
&context->hex.regions[data->selected_region]->data.position,
context->hex.regions[data->selected_region]->region,
offsetof(GPUHexRegion, position),
sizeof(uint32_t),
context->render.current_frame,
&context->render);
}
update_region_info_ui(context);
break;
case GLFW_KEY_K:
if(data->selected_region < MAX_LOADED_REGIONS) {
context->hex.regions[data->selected_region]->data.position.q -= 1;
add_transfer(
&context->hex.regions[data->selected_region]->data.position.q,
context->hex.regions[data->selected_region]->region,
offsetof(GPUHexRegion, position) + offsetof(HexCoord, q),
sizeof(uint32_t),
context->render.current_frame,
&context->render);
}
update_region_info_ui(context);
break;
case GLFW_KEY_J:
if(data->selected_region < MAX_LOADED_REGIONS) {
context->hex.regions[data->selected_region]->data.position.r += 1;
add_transfer(
&context->hex.regions[data->selected_region]->data.position.r,
context->hex.regions[data->selected_region]->region,
offsetof(GPUHexRegion, position) + offsetof(HexCoord, r),
sizeof(uint32_t),
context->render.current_frame,
&context->render);
}
update_region_info_ui(context);
break;
case GLFW_KEY_L:
if(data->selected_region < MAX_LOADED_REGIONS) {
context->hex.regions[data->selected_region]->data.position.r -= 1;
add_transfer(
&context->hex.regions[data->selected_region]->data.position.r,
context->hex.regions[data->selected_region]->region,
offsetof(GPUHexRegion, position) + offsetof(HexCoord, r),
sizeof(uint32_t),
context->render.current_frame,
&context->render);
}
update_region_info_ui(context);
break;
case GLFW_KEY_O:
if(data->selected_region < MAX_LOADED_REGIONS) {
context->hex.regions[data->selected_region]->data.y += 1;
add_transfer(
&context->hex.regions[data->selected_region]->data.y,
context->hex.regions[data->selected_region]->region,
offsetof(GPUHexRegion, y),
sizeof(int32_t),
context->render.current_frame,
&context->render);
}
update_region_info_ui(context);
break;
case GLFW_KEY_U:
if(data->selected_region < MAX_LOADED_REGIONS) {
context->hex.regions[data->selected_region]->data.y -= 1;
add_transfer(
&context->hex.regions[data->selected_region]->data.y,
context->hex.regions[data->selected_region]->region,
offsetof(GPUHexRegion, y),
sizeof(int32_t),
context->render.current_frame,
&context->render);
}
update_region_info_ui(context);
break;
case GLFW_KEY_Y:
if(data->clicked_region < MAX_LOADED_REGIONS && data->clicked_vertex != 0) {
region = context->hex.regions[data->clicked_region];
float height = region->data.hexes[data->clicked_hex].height[data->clicked_vertex-1] + 0.1;
if(~mods & GLFW_MOD_CONTROL) {
uint32_t n_vertex[2], n_hex[2];
HexCoord n_region[2];
HexCoord world, region_center;
region_qr(region->data.position, &region_center);
hex_qr(data->clicked_hex, &world);
hex_add(region_center, &world);
hex_vertex_neighbors(data->clicked_vertex, world, n_vertex, n_region, n_hex);
uint32_t n0, n1;
first_matching_region(n_region[0], region->data.y, &n0, &context->hex);
first_matching_region(n_region[1], region->data.y, &n1, &context->hex);
if(n0 != MAX_LOADED_REGIONS) set_vertex_height(height, n0, n_hex[0], n_vertex[0], context);
if(n1 != MAX_LOADED_REGIONS) set_vertex_height(height, n1, n_hex[1], n_vertex[1], context);
}
set_vertex_height(height, data->clicked_region, data->clicked_hex, data->clicked_vertex, context);
update_hex_info_ui(context);
}
break;
void move_cam_down(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
move_cam(context, action, mods, 1, -1);
}
case GLFW_KEY_H:
if(data->clicked_region < MAX_LOADED_REGIONS && data->clicked_vertex != 0) {
region = context->hex.regions[data->clicked_region];
float height = region->data.hexes[data->clicked_hex].height[data->clicked_vertex-1] - 0.1;
void move_cam_left(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
move_cam(context, action, mods, 0, -1);
}
if(~mods & GLFW_MOD_CONTROL) {
uint32_t n_vertex[2], n_hex[2];
HexCoord n_region[2];
HexCoord world, region_center;
void move_cam_right(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
move_cam(context, action, mods, 0, 1);
}
region_qr(region->data.position, &region_center);
hex_qr(data->clicked_hex, &world);
hex_add(region_center, &world);
hex_vertex_neighbors(data->clicked_vertex, world, n_vertex, n_region, n_hex);
void move_cam_forward(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
move_cam(context, action, mods, 2, 1);
}
uint32_t n0, n1;
first_matching_region(n_region[0], region->data.y, &n0, &context->hex);
first_matching_region(n_region[1], region->data.y, &n1, &context->hex);
void move_cam_backwards(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
move_cam(context, action, mods, 2, -1);
}
if(n0 != MAX_LOADED_REGIONS) set_vertex_height(height, n0, n_hex[0], n_vertex[0], context);
if(n1 != MAX_LOADED_REGIONS) set_vertex_height(height, n1, n_hex[1], n_vertex[1], context);
}
set_vertex_height(height, data->clicked_region, data->clicked_hex, data->clicked_vertex, context);
update_hex_info_ui(context);
}
break;
case GLFW_KEY_E:
if(data->clicked_region < MAX_LOADED_REGIONS) {
region = context->hex.regions[data->clicked_region];
uint32_t n_vertex[2], n_hex[2];
HexCoord n_region[2];
HexCoord world, region_center;
if(data->clicked_vertex != 0 && data->clicked_vertex <= 6) {
region_qr(region->data.position, &region_center);
hex_qr(data->clicked_hex, &world);
hex_add(region_center, &world);
hex_vertex_neighbors(data->clicked_vertex, world, n_vertex, n_region, n_hex);
uint32_t n0, n1;
first_matching_region(n_region[0], region->data.y, &n0, &context->hex);
first_matching_region(n_region[1], region->data.y, &n1, &context->hex);
if(n0 != MAX_LOADED_REGIONS) set_vertex_color(data->current, n0, n_hex[0], n_vertex[0], context);
if(n1 != MAX_LOADED_REGIONS) set_vertex_color(data->current, n1, n_hex[1], n_vertex[1], context);
}
set_vertex_color(data->current, data->clicked_region, data->clicked_hex, data->clicked_vertex, context);
update_hex_info_ui(context);
}
break;
void clear_mode(EditorData* data, ClientContext* context, int action, int mods) {
(void)mods;
if(action == GLFW_PRESS) {
data->mode = MODE_NONE;
update_mode_string(context, data);
data->selected_count = 0;
unload_container(COLOR_PICK_CONTAINER_ID, &context->render, &context->ui);
}
}
void enter_vertex_mode(EditorData* data, ClientContext* context, int action, int mods) {
(void)mods;
if(action == GLFW_PRESS) {
data->mode = MODE_VERTEX;
update_mode_string(context, data);
data->selected_count = 0;
color_ui(context);
}
}
void enter_neighbor_mode(EditorData* data, ClientContext* context, int action, int mods) {
(void)mods;
if(action == GLFW_PRESS) {
data->mode = MODE_NEIGHBOR;
update_mode_string(context, data);
data->selected_count = 0;
color_ui(context);
}
}
void enter_hex_mode(EditorData* data, ClientContext* context, int action, int mods) {
(void)mods;
if(action == GLFW_PRESS) {
data->mode = MODE_HEX;
update_mode_string(context, data);
data->selected_count = 0;
color_ui(context);
}
}
return false;
void enter_region_mode(EditorData* data, ClientContext* context, int action, int mods) {
(void)mods;
if(action == GLFW_PRESS) {
data->mode = MODE_REGION;
update_mode_string(context, data);
data->selected_count = 0;
unload_container(COLOR_PICK_CONTAINER_ID, &context->render, &context->ui);
}
}
void editor_startup(ClientContext* context) {
region_info_ui(context);
hex_info_ui(context);
color_ui(context);
mode_string_ui(context);
// TODO: Remove when region mode is implemented
add_hex_region(context);
}
void resize_selected(EditorData* data, unsigned int size) {
uint32_t* new_regions = malloc(sizeof(uint32_t)*size);
uint32_t* new_hexes = malloc(sizeof(uint32_t)*size);
uint32_t* new_vertices = malloc(sizeof(uint32_t)*size);
if(data->selected_regions != NULL) {
memcpy(new_regions, data->selected_regions, data->selected_count);
free(data->selected_regions);
}
if(data->selected_hexes != NULL) {
memcpy(new_hexes, data->selected_hexes, data->selected_count);
free(data->selected_hexes);
}
if(data->selected_vertices != NULL) {
memcpy(new_vertices, data->selected_vertices, data->selected_count);
}
data->selected_regions = new_regions;
data->selected_hexes = new_hexes;
data->selected_vertices = new_vertices;
data->selected_max = size;
}
int main() {
EditorData* data = malloc(sizeof(EditorData));
memset(data, 0, sizeof(EditorData));
data->selected_region = MAX_LOADED_REGIONS;
data->clicked_region = MAX_LOADED_REGIONS;
data->clicked_hex = UINT32_MAX;
data->clicked_vertex = UINT32_MAX;
data->selected_count = 0;
resize_selected(data, 1);
data->mode_key_counts[MODE_NONE] = 15;
for(int i = 0; i < MODE_MAX_ENUM; i++) {
data->mode_keys[i] = malloc(sizeof(ModeKey)*data->mode_key_counts[i]);
}
// Mode Switches
data->mode_keys[MODE_NONE][0].key = GLFW_KEY_ESCAPE;
data->mode_keys[MODE_NONE][0].logic = clear_mode;
data->mode_keys[MODE_NONE][1].key = GLFW_KEY_V;
data->mode_keys[MODE_NONE][1].logic = enter_vertex_mode;
data->mode_keys[MODE_NONE][2].key = GLFW_KEY_N;
data->mode_keys[MODE_NONE][2].logic = enter_neighbor_mode;
data->mode_keys[MODE_NONE][3].key = GLFW_KEY_H;
data->mode_keys[MODE_NONE][3].logic = enter_hex_mode;
data->mode_keys[MODE_NONE][4].key = GLFW_KEY_R;
data->mode_keys[MODE_NONE][4].logic = enter_region_mode;
// Camera Movement
data->mode_keys[MODE_NONE][5].key = GLFW_KEY_SPACE;
data->mode_keys[MODE_NONE][5].logic = move_cam_up;
data->mode_keys[MODE_NONE][6].key = GLFW_KEY_LEFT_SHIFT;
data->mode_keys[MODE_NONE][6].logic = move_cam_down;
data->mode_keys[MODE_NONE][7].key = GLFW_KEY_LEFT;
data->mode_keys[MODE_NONE][7].logic = move_cam_left;
data->mode_keys[MODE_NONE][8].key = GLFW_KEY_RIGHT;
data->mode_keys[MODE_NONE][8].logic = move_cam_right;
data->mode_keys[MODE_NONE][9].key = GLFW_KEY_UP;
data->mode_keys[MODE_NONE][9].logic = move_cam_forward;
data->mode_keys[MODE_NONE][10].key = GLFW_KEY_DOWN;
data->mode_keys[MODE_NONE][10].logic = move_cam_backwards;
// Camera Spin
data->mode_keys[MODE_NONE][11].key = GLFW_KEY_A;
data->mode_keys[MODE_NONE][11].logic = spin_cam_left;
data->mode_keys[MODE_NONE][12].key = GLFW_KEY_D;
data->mode_keys[MODE_NONE][12].logic = spin_cam_right;
data->mode_keys[MODE_NONE][13].key = GLFW_KEY_W;
data->mode_keys[MODE_NONE][13].logic = spin_cam_up;
data->mode_keys[MODE_NONE][14].key = GLFW_KEY_S;
data->mode_keys[MODE_NONE][14].logic = spin_cam_down;
return run_app(data, editor_startup, NULL, NULL, editor_key_callback, NULL, NULL, NULL);
}

@ -12,7 +12,7 @@ void text_callback(GLFWwindow* window, unsigned int codepoint) {
&context->render,
codepoint)) return;
if(context->app_text != NULL && context->app_text(context, codepoint)) return;
if(context->app_text != NULL) context->app_text(context, codepoint);
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
@ -29,84 +29,7 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod
&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;
}
if(context->app_key != NULL) context->app_key(context, key, action, mods);
}
void button_callback(GLFWwindow* window, int button, int action, int mods) {
@ -154,8 +77,6 @@ void button_callback(GLFWwindow* window, int button, int action, int mods) {
}
}
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++) {
@ -176,15 +97,7 @@ void button_callback(GLFWwindow* window, int button, int action, int mods) {
}
}
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;
}
}
if(context->app_button != NULL) context->app_button(context, cursor[0], cursor[1], button, action, mods);
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
@ -203,8 +116,6 @@ void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
&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,
@ -228,9 +139,9 @@ void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
break;
}
}
} else {
context->zoom = -yoffset;
}
if(context->app_scroll != NULL) context->app_scroll(context, xoffset, yoffset);
}
void cursor_callback(GLFWwindow* window, double xpos, double ypos) {
@ -239,57 +150,48 @@ void cursor_callback(GLFWwindow* window, double xpos, double ypos) {
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->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;
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;
}
}
}
if(context->app_cursor != NULL) context->app_cursor(context, xpos, ypos);
}
int app_main(ClientContext* context) {
@ -303,16 +205,13 @@ int app_main(ClientContext* context) {
// 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 ||
if((context->spin[0] != 0 || context->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)) {
@ -322,16 +221,14 @@ int app_main(ClientContext* context) {
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;
context->rotation[0] += (float)context->spin[0]*delta_time*context->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;
context->rotation[1] += (float)context->spin[1]*delta_time*context->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) {
@ -393,8 +290,7 @@ int run_app(
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->spin_speed = 1.0;
context->zoom_speed = 1.0;
context->move_speed = 0.1;

@ -1064,6 +1064,10 @@ VkResult init_vulkan(GLFWwindow* window, RenderContext* context) {
return VK_ERROR_VALIDATION_FAILED_EXT;
}
context->swapchain_command_buffer_record_id = 1;
context->swapchain_command_buffer_record_ids = malloc(sizeof(uint64_t)*context->swapchain_image_count);
memset(context->swapchain_command_buffer_record_ids, 0, sizeof(uint64_t)*context->swapchain_image_count);
VK_RESULT(create_image_views(
context->device,
context->swapchain_image_count,

@ -227,10 +227,45 @@ VkResult create_ui_pipeline(
return VK_SUCCESS;
}
VkResult create_container(
VkResult unload_container(
uint32_t id,
RenderContext* gpu,
UIContext* context) {
uint32_t index = 0xFFFFFFFF;
for(uint32_t i = 0; i < context->max_containers; i++) {
if(context->containers[i].id == id) {
index = i;
break;
}
}
if(index == 0xFFFFFFFF) {
return VK_ERROR_VALIDATION_FAILED_EXT;
}
context->containers[index].id = 0;
for(uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
vmaDestroyBuffer(gpu->allocator, context->containers[index].container[i], context->containers[index].container_memory[i]);
context->containers[index].address[i] = 0;
}
context->containers[index].layer_count = 0;
return VK_SUCCESS;
}
VkResult load_container(
ContainerInput* container,
RenderContext* gpu,
UIContext* context) {
if(container == NULL) return VK_ERROR_VALIDATION_FAILED_EXT;
if(container->id == 0) return VK_ERROR_VALIDATION_FAILED_EXT;
for(uint32_t i = 0; i < context->max_containers; i++) {
if(context->containers[i].id == container->id) return VK_ERROR_VALIDATION_FAILED_EXT;
}
uint32_t index = 0xFFFFFFFF;
for(uint32_t i = 0; i < context->max_containers; i++) {
if(context->containers[i].id == 0x00000000) {
@ -1167,7 +1202,7 @@ Container* context_container(uint32_t container_id, UIContext* ui) {
}
VkResult update_ui_string(
char* string,
const char* string,
uint32_t container_id,
uint32_t layer_index,
uint32_t string_index,