Fixed camera logic and simplified

main
noah metz 2026-07-27 22:46:18 -06:00
parent 9ecce26d18
commit 4210ff1aba
2 changed files with 83 additions and 107 deletions

@ -28,13 +28,16 @@ const char* ModeStrings[] = {
}; };
typedef struct EditorDataStruct EditorData; typedef struct EditorDataStruct EditorData;
typedef struct ModeKeyStruct ModeKey;
typedef void(*ModeKeyCallback)(EditorData* data, ClientContext* context, int action, int mods); typedef void(*ModeKeyCallback)(EditorData* data, ClientContext* context, ModeKey* binding, int action, int mods);
typedef struct ModeKeyStruct { struct ModeKeyStruct {
int key; int key;
ModeKeyCallback logic; ModeKeyCallback logic;
} ModeKey; int axis;
float amount;
};
struct EditorDataStruct { struct EditorDataStruct {
EditorMode mode; EditorMode mode;
@ -153,86 +156,59 @@ VkResult update_mode_string(ClientContext* context, EditorData* data) {
return ui_lua_call(&context->ui, &context->render, container, "set_mode", ModeStrings[data->mode]); return ui_lua_call(&context->ui, &context->render, container, "set_mode", ModeStrings[data->mode]);
} }
// Movement/spin keys are only ever seen by editor.c when no UI element has
// focus (engine.c routes key events to the focused element first). If focus
// is gained while a key is held, its release never reaches us and the
// accumulator in move_cam/spin_cam is left stuck. Zeroing here every frame a
// UI element is focused keeps the camera from drifting forever in that case.
void editor_frame_callback(ClientContext* context) {
if(context->ui.active_container != NULL) {
context->velocity[0] = 0;
context->velocity[1] = 0;
context->velocity[2] = 0;
context->spin[0] = 0;
context->spin[1] = 0;
}
}
void editor_key_callback(ClientContext* context, int key, int action, int mods) { void editor_key_callback(ClientContext* context, int key, int action, int mods) {
EditorData* data = context->app_data; EditorData* data = context->app_data;
for(uint32_t i = 0; i < data->mode_key_counts[data->mode]; i++) { for(uint32_t i = 0; i < data->mode_key_counts[data->mode]; i++) {
if(data->mode_keys[data->mode][i].key == key) { if(data->mode_keys[data->mode][i].key == key) {
data->mode_keys[data->mode][i].logic(data, context, action, mods); data->mode_keys[data->mode][i].logic(data, context, &data->mode_keys[data->mode][i], action, mods);
return; return;
} }
} }
for(uint32_t i = 0; i < data->mode_key_counts[MODE_NONE]; i++) { for(uint32_t i = 0; i < data->mode_key_counts[MODE_NONE]; i++) {
if(data->mode_keys[MODE_NONE][i].key == key) { if(data->mode_keys[MODE_NONE][i].key == key) {
data->mode_keys[MODE_NONE][i].logic(data, context, action, mods); data->mode_keys[MODE_NONE][i].logic(data, context, &data->mode_keys[MODE_NONE][i], action, mods);
return; return;
} }
} }
} }
void spin_cam(ClientContext* context, int action, int mods, unsigned int axis, float amount) { void spin_cam_key(EditorData* data, ClientContext* context, ModeKey* binding, int action, int mods) {
(void)mods;
if(action == GLFW_PRESS) context->spin[axis] += amount;
else if(action == GLFW_RELEASE) context->spin[axis] -= amount;
}
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);
}
void spin_cam_up(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
spin_cam(context, action, mods, 1, 1);
}
void spin_cam_down(EditorData* data, ClientContext* context, int action, int mods) {
(void)data; (void)data;
spin_cam(context, action, mods, 1, -1);
}
void move_cam(ClientContext* context, int action, int mods, unsigned int axis, float amount) {
(void)mods; (void)mods;
if(action == GLFW_PRESS) context->velocity[axis] += amount; if(action == GLFW_PRESS) context->spin[binding->axis] += binding->amount;
else if(action == GLFW_RELEASE) context->velocity[axis] -= amount; else if(action == GLFW_RELEASE) context->spin[binding->axis] -= binding->amount;
}
void move_cam_up(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
move_cam(context, action, mods, 1, 1);
}
void move_cam_down(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
move_cam(context, action, mods, 1, -1);
} }
void move_cam_left(EditorData* data, ClientContext* context, int action, int mods) { void move_cam_key(EditorData* data, ClientContext* context, ModeKey* binding, int action, int mods) {
(void)data; (void)data;
move_cam(context, action, mods, 0, -1); (void)mods;
} if(action == GLFW_PRESS) context->velocity[binding->axis] += binding->amount;
else if(action == GLFW_RELEASE) context->velocity[binding->axis] -= binding->amount;
void move_cam_right(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
move_cam(context, action, mods, 0, 1);
}
void move_cam_forward(EditorData* data, ClientContext* context, int action, int mods) {
(void)data;
move_cam(context, action, mods, 2, 1);
} }
void move_cam_backwards(EditorData* data, ClientContext* context, int action, int mods) { void editor_scroll_callback(ClientContext* context, double x, double y) {
(void)data; (void)x;
move_cam(context, action, mods, 2, -1); context->zoom = (int32_t)y;
} }
void clear_mode(EditorData* data, ClientContext* context, int action, int mods) { void clear_mode(EditorData* data, ClientContext* context, ModeKey* binding, int action, int mods) {
(void)binding;
(void)mods; (void)mods;
if(action == GLFW_PRESS) { if(action == GLFW_PRESS) {
data->mode = MODE_NONE; data->mode = MODE_NONE;
@ -242,7 +218,8 @@ void clear_mode(EditorData* data, ClientContext* context, int action, int mods)
} }
} }
void enter_vertex_mode(EditorData* data, ClientContext* context, int action, int mods) { void enter_vertex_mode(EditorData* data, ClientContext* context, ModeKey* binding, int action, int mods) {
(void)binding;
(void)mods; (void)mods;
if(action == GLFW_PRESS) { if(action == GLFW_PRESS) {
data->mode = MODE_VERTEX; data->mode = MODE_VERTEX;
@ -252,7 +229,8 @@ void enter_vertex_mode(EditorData* data, ClientContext* context, int action, int
} }
} }
void enter_neighbor_mode(EditorData* data, ClientContext* context, int action, int mods) { void enter_neighbor_mode(EditorData* data, ClientContext* context, ModeKey* binding, int action, int mods) {
(void)binding;
(void)mods; (void)mods;
if(action == GLFW_PRESS) { if(action == GLFW_PRESS) {
data->mode = MODE_NEIGHBOR; data->mode = MODE_NEIGHBOR;
@ -262,7 +240,8 @@ void enter_neighbor_mode(EditorData* data, ClientContext* context, int action, i
} }
} }
void enter_hex_mode(EditorData* data, ClientContext* context, int action, int mods) { void enter_hex_mode(EditorData* data, ClientContext* context, ModeKey* binding, int action, int mods) {
(void)binding;
(void)mods; (void)mods;
if(action == GLFW_PRESS) { if(action == GLFW_PRESS) {
data->mode = MODE_HEX; data->mode = MODE_HEX;
@ -272,7 +251,8 @@ void enter_hex_mode(EditorData* data, ClientContext* context, int action, int mo
} }
} }
void enter_region_mode(EditorData* data, ClientContext* context, int action, int mods) { void enter_region_mode(EditorData* data, ClientContext* context, ModeKey* binding, int action, int mods) {
(void)binding;
(void)mods; (void)mods;
if(action == GLFW_PRESS) { if(action == GLFW_PRESS) {
data->mode = MODE_REGION; data->mode = MODE_REGION;
@ -324,41 +304,26 @@ int main() {
data->mode_keys[i] = malloc(sizeof(ModeKey)*data->mode_key_counts[i]); data->mode_keys[i] = malloc(sizeof(ModeKey)*data->mode_key_counts[i]);
} }
// Mode Switches // Mode Switches
data->mode_keys[MODE_NONE][0].key = GLFW_KEY_ESCAPE; data->mode_keys[MODE_NONE][0] = (ModeKey){GLFW_KEY_ESCAPE, clear_mode, 0, 0};
data->mode_keys[MODE_NONE][0].logic = clear_mode; data->mode_keys[MODE_NONE][1] = (ModeKey){GLFW_KEY_V, enter_vertex_mode, 0, 0};
data->mode_keys[MODE_NONE][1].key = GLFW_KEY_V; data->mode_keys[MODE_NONE][2] = (ModeKey){GLFW_KEY_N, enter_neighbor_mode, 0, 0};
data->mode_keys[MODE_NONE][1].logic = enter_vertex_mode; data->mode_keys[MODE_NONE][3] = (ModeKey){GLFW_KEY_H, enter_hex_mode, 0, 0};
data->mode_keys[MODE_NONE][2].key = GLFW_KEY_N; data->mode_keys[MODE_NONE][4] = (ModeKey){GLFW_KEY_R, enter_region_mode, 0, 0};
data->mode_keys[MODE_NONE][2].logic = enter_neighbor_mode;
data->mode_keys[MODE_NONE][3].key = GLFW_KEY_H; // Camera Movement (axis: 0 = strafe x, 1 = up/down, 2 = forward/back)
data->mode_keys[MODE_NONE][3].logic = enter_hex_mode; data->mode_keys[MODE_NONE][5] = (ModeKey){GLFW_KEY_SPACE, move_cam_key, 1, 1};
data->mode_keys[MODE_NONE][4].key = GLFW_KEY_R; data->mode_keys[MODE_NONE][6] = (ModeKey){GLFW_KEY_LEFT_SHIFT, move_cam_key, 1, -1};
data->mode_keys[MODE_NONE][4].logic = enter_region_mode; data->mode_keys[MODE_NONE][7] = (ModeKey){GLFW_KEY_LEFT, move_cam_key, 0, -1};
data->mode_keys[MODE_NONE][8] = (ModeKey){GLFW_KEY_RIGHT, move_cam_key, 0, 1};
// Camera Movement data->mode_keys[MODE_NONE][9] = (ModeKey){GLFW_KEY_UP, move_cam_key, 2, 1};
data->mode_keys[MODE_NONE][5].key = GLFW_KEY_SPACE; data->mode_keys[MODE_NONE][10] = (ModeKey){GLFW_KEY_DOWN, move_cam_key, 2, -1};
data->mode_keys[MODE_NONE][5].logic = move_cam_up;
data->mode_keys[MODE_NONE][6].key = GLFW_KEY_LEFT_SHIFT; // Camera Spin (axis: 0 = yaw, 1 = pitch)
data->mode_keys[MODE_NONE][6].logic = move_cam_down; data->mode_keys[MODE_NONE][11] = (ModeKey){GLFW_KEY_A, spin_cam_key, 0, -1};
data->mode_keys[MODE_NONE][7].key = GLFW_KEY_LEFT; data->mode_keys[MODE_NONE][12] = (ModeKey){GLFW_KEY_D, spin_cam_key, 0, 1};
data->mode_keys[MODE_NONE][7].logic = move_cam_left; data->mode_keys[MODE_NONE][13] = (ModeKey){GLFW_KEY_W, spin_cam_key, 1, 1};
data->mode_keys[MODE_NONE][8].key = GLFW_KEY_RIGHT; data->mode_keys[MODE_NONE][14] = (ModeKey){GLFW_KEY_S, spin_cam_key, 1, -1};
data->mode_keys[MODE_NONE][8].logic = move_cam_right;
data->mode_keys[MODE_NONE][9].key = GLFW_KEY_UP; return run_app(data, editor_startup, editor_frame_callback, NULL, editor_key_callback, NULL, editor_scroll_callback, NULL);
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);
} }

@ -216,15 +216,26 @@ int app_main(ClientContext* context) {
context->rotation[1] = 0; context->rotation[1] = 0;
} }
context->position[0] += - context->velocity[2]*context->move_speed*cos(context->rotation[0]) float move_x = context->velocity[0];
- context->velocity[0]*context->move_speed*sin(context->rotation[0]); float move_z = context->velocity[2];
float move_mag = sqrt(move_x*move_x + move_z*move_z);
if(move_mag > 1) {
move_x /= move_mag;
move_z /= move_mag;
}
context->position[0] += - move_z*context->move_speed*cos(context->rotation[0])
- move_x*context->move_speed*sin(context->rotation[0]);
context->position[2] += context->velocity[0]*context->move_speed*cos(context->rotation[0]) context->position[2] += move_x*context->move_speed*cos(context->rotation[0])
- context->velocity[2]*context->move_speed*sin(context->rotation[0]); - move_z*context->move_speed*sin(context->rotation[0]);
context->position[1] += context->velocity[1]*context->move_speed; context->position[1] += context->velocity[1]*context->move_speed;
context->distance += context->zoom*delta_time*context->zoom_speed; // context->zoom is a one-frame scroll impulse (reset to 0 each frame,
// above), not a held input like spin/velocity, so it isn't scaled by
// delta_time.
context->distance += context->zoom*context->zoom_speed;
if(context->distance < 1) { if(context->distance < 1) {
context->distance = 1; context->distance = 1;
} }
@ -272,7 +283,7 @@ int run_app(
context->rotation[1] = M_PI/4; context->rotation[1] = M_PI/4;
context->distance = 25; context->distance = 25;
context->spin_speed = 1.0; context->spin_speed = 1.0;
context->zoom_speed = 1.0; context->zoom_speed = 0.5;
context->move_speed = 0.1; context->move_speed = 0.1;
memset(&context->render, 0, sizeof(RenderContext)); memset(&context->render, 0, sizeof(RenderContext));