|
|
|
@ -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,
|
|
|
|
|
GPUString string = {
|
|
|
|
|
.pos = {0, 32},
|
|
|
|
|
.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},
|
|
|
|
|
.length = strlen(ModeStrings[MODE_NONE]),
|
|
|
|
|
.color = {1, 1, 1, 1},
|
|
|
|
|
.size = 32,
|
|
|
|
|
.offset = 25,
|
|
|
|
|
.length = 0,
|
|
|
|
|
.font = 0,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
EditorData* data = context->app_data;
|
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult update_hex_info_ui(ClientContext* context) {
|
|
|
|
|
char temp[20];
|
|
|
|
|
VkResult result;
|
|
|
|
|
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->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 = ®ion->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, ®ion_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));
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool editor_key_callback(ClientContext* context, int key, int action, int mods) {
|
|
|
|
|
uint32_t start, next_region;
|
|
|
|
|
void spin_cam_left(EditorData* data, ClientContext* context, int action, int mods) {
|
|
|
|
|
(void)data;
|
|
|
|
|
spin_cam(context, action, mods, 0, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(action != GLFW_PRESS) return false;
|
|
|
|
|
void spin_cam_right(EditorData* data, ClientContext* context, int action, int mods) {
|
|
|
|
|
(void)data;
|
|
|
|
|
spin_cam(context, action, mods, 0, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EditorData* data = context->app_data;
|
|
|
|
|
HexRegion* region = NULL;
|
|
|
|
|
void spin_cam_up(EditorData* data, ClientContext* context, int action, int mods) {
|
|
|
|
|
(void)data;
|
|
|
|
|
spin_cam(context, action, mods, 1, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(key) {
|
|
|
|
|
case GLFW_KEY_EQUAL:
|
|
|
|
|
data->selected_region = add_hex_region(context);
|
|
|
|
|
update_region_info_ui(context);
|
|
|
|
|
update_hex_info_ui(context);
|
|
|
|
|
break;
|
|
|
|
|
void spin_cam_down(EditorData* data, ClientContext* context, int action, int mods) {
|
|
|
|
|
(void)data;
|
|
|
|
|
spin_cam(context, action, mods, 1, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
void move_cam_up(EditorData* data, ClientContext* context, int action, int mods) {
|
|
|
|
|
(void)data;
|
|
|
|
|
move_cam(context, action, mods, 1, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
void move_cam_down(EditorData* data, ClientContext* context, int action, int mods) {
|
|
|
|
|
(void)data;
|
|
|
|
|
move_cam(context, action, mods, 1, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
void move_cam_left(EditorData* data, ClientContext* context, int action, int mods) {
|
|
|
|
|
(void)data;
|
|
|
|
|
move_cam(context, action, mods, 0, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
void move_cam_right(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_forward(EditorData* data, ClientContext* context, int action, int mods) {
|
|
|
|
|
(void)data;
|
|
|
|
|
move_cam(context, action, mods, 2, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
region_qr(region->data.position, ®ion_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_backwards(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 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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
set_vertex_height(height, data->clicked_region, data->clicked_hex, data->clicked_vertex, context);
|
|
|
|
|
update_hex_info_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);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(~mods & GLFW_MOD_CONTROL) {
|
|
|
|
|
uint32_t n_vertex[2], n_hex[2];
|
|
|
|
|
HexCoord n_region[2];
|
|
|
|
|
HexCoord world, region_center;
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
region_qr(region->data.position, ®ion_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 editor_startup(ClientContext* context) {
|
|
|
|
|
mode_string_ui(context);
|
|
|
|
|
// TODO: Remove when region mode is implemented
|
|
|
|
|
add_hex_region(context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 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(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);
|
|
|
|
|
if(data->selected_regions != NULL) {
|
|
|
|
|
memcpy(new_regions, data->selected_regions, data->selected_count);
|
|
|
|
|
free(data->selected_regions);
|
|
|
|
|
}
|
|
|
|
|
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, ®ion_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);
|
|
|
|
|
if(data->selected_hexes != NULL) {
|
|
|
|
|
memcpy(new_hexes, data->selected_hexes, data->selected_count);
|
|
|
|
|
free(data->selected_hexes);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if(data->selected_vertices != NULL) {
|
|
|
|
|
memcpy(new_vertices, data->selected_vertices, data->selected_count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void editor_startup(ClientContext* context) {
|
|
|
|
|
region_info_ui(context);
|
|
|
|
|
hex_info_ui(context);
|
|
|
|
|
color_ui(context);
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|