Browse Source

Implement UIState buffer caching to eliminate per-frame malloc/free calls

main
cinnaboot 5 months ago
parent
commit
b37497a504
  1. 3
      src/main.cpp
  2. 2
      src/maneuver.cpp
  3. 6
      src/simulation.cpp
  4. 2
      src/simulation.h
  5. 275
      src/ui_renderer.cpp
  6. 12
      src/ui_renderer.h

3
src/main.cpp

@ -45,6 +45,8 @@ void run_gui_simulation(SimulationState* sim) {
ui_state.maneuver_list_scroll = 0;
ui_state.selected_maneuver_index = -1;
ui_state_init_buffers(&ui_state);
ui_state.maneuver_dialog.open = false;
ui_state.maneuver_dialog.active_tab = MD_TAB_CREATE;
ui_state.maneuver_dialog.craft_index = -1;
@ -175,6 +177,7 @@ void run_gui_simulation(SimulationState* sim) {
}
close_renderer(&render_state);
ui_state_free_buffers(&ui_state);
printf("\nSimulation ended. Final time: %.2f days\n", sim->time / 86400.0);
}

2
src/maneuver.cpp

@ -252,6 +252,7 @@ int add_maneuver_to_simulation(SimulationState* sim, Maneuver* maneuver) {
sim->maneuvers[new_idx].executed = false;
sim->maneuvers[new_idx].executed_time = 0.0;
sim->maneuver_count++;
increment_sim_version(sim);
return new_idx;
}
@ -268,6 +269,7 @@ bool remove_maneuver_by_index(SimulationState* sim, int index) {
}
sim->maneuver_count--;
increment_sim_version(sim);
return true;
}

6
src/simulation.cpp

@ -64,6 +64,7 @@ int add_spacecraft(SimulationState* sim, Spacecraft* craft) {
int new_idx = sim->craft_count;
sim->spacecraft[new_idx] = *craft;
sim->craft_count++;
increment_sim_version(sim);
return new_idx;
}
@ -98,6 +99,7 @@ int add_body_to_simulation(SimulationState* sim, CelestialBody* body) {
sim->bodies[new_idx].global_position = body->global_position;
sim->bodies[new_idx].global_velocity = body->global_velocity;
increment_sim_version(sim);
return new_idx;
}
@ -393,3 +395,7 @@ OrbitalAnalysis calculate_orbital_elements(CelestialBody* body, CelestialBody* p
return elem;
}
void increment_sim_version(SimulationState* sim) {
sim->version++;
}

2
src/simulation.h

@ -46,11 +46,13 @@ struct SimulationState {
double time;
double dt;
char config_name[256];
int version;
};
// Simulation management functions
SimulationState* create_simulation(int max_bodies, int max_craft, int max_maneuvers, double time_step);
void destroy_simulation(SimulationState* sim);
void increment_sim_version(SimulationState* sim);
// Dynamic body management
int add_body_to_simulation(SimulationState* sim, CelestialBody* body);

275
src/ui_renderer.cpp

@ -94,28 +94,43 @@ void render_body_list_ui(SimulationState* sim, RenderState* render_state, UIStat
// Create list string for raygui (NULL-terminated)
// Include both bodies and spacecraft
int total_items = sim->body_count + sim->craft_count;
int buffer_size = total_items * (64 + 3 + 1) + 1; // Extra space for "🚀 " prefix
char* list_text = (char*)malloc(buffer_size);
if (!list_text) return;
list_text[0] = '\0';
int offset = 0;
int item_index = 0;
// Add bodies to list
for (int i = 0; i < sim->body_count; i++) {
if (item_index > 0) {
offset += snprintf(list_text + offset, buffer_size - offset, ";");
// Check if buffer needs rebuilding
bool needs_rebuild = (ui_state->sim_version != sim->version) || (ui_state->body_list_buffer == NULL);
if (needs_rebuild) {
int buffer_size = total_items * (64 + 3 + 1) + 1;
if (ui_state->body_list_buffer == NULL || ui_state->body_list_buffer_size < buffer_size) {
if (ui_state->body_list_buffer != NULL) {
free(ui_state->body_list_buffer);
}
ui_state->body_list_buffer = (char*)malloc(buffer_size);
if (!ui_state->body_list_buffer) return;
ui_state->body_list_buffer_size = buffer_size;
}
offset += snprintf(list_text + offset, buffer_size - offset, "%s", sim->bodies[i].name);
item_index++;
}
// Add spacecraft to list with "🚀 " prefix
for (int i = 0; i < sim->craft_count; i++) {
offset += snprintf(list_text + offset, buffer_size - offset, ";");
offset += snprintf(list_text + offset, buffer_size - offset, "🚀 %s", sim->spacecraft[i].name);
item_index++;
ui_state->body_list_buffer[0] = '\0';
int offset = 0;
int item_index = 0;
// Add bodies to list
for (int i = 0; i < sim->body_count; i++) {
if (item_index > 0) {
offset += snprintf(ui_state->body_list_buffer + offset, ui_state->body_list_buffer_size - offset, ";");
}
offset += snprintf(ui_state->body_list_buffer + offset, ui_state->body_list_buffer_size - offset, "%s", sim->bodies[i].name);
item_index++;
}
// Add spacecraft to list with "🚀 " prefix
for (int i = 0; i < sim->craft_count; i++) {
offset += snprintf(ui_state->body_list_buffer + offset, ui_state->body_list_buffer_size - offset, ";");
offset += snprintf(ui_state->body_list_buffer + offset, ui_state->body_list_buffer_size - offset, "🚀 %s", sim->spacecraft[i].name);
item_index++;
}
ui_state->sim_version = sim->version;
}
// Draw window (no close button - panels always shown)
@ -130,7 +145,7 @@ void render_body_list_ui(SimulationState* sim, RenderState* render_state, UIStat
};
int previous_active = ui_state->body_list_active;
GuiListView(list_bounds, list_text, &ui_state->body_list_scroll, &ui_state->body_list_active);
GuiListView(list_bounds, ui_state->body_list_buffer, &ui_state->body_list_scroll, &ui_state->body_list_active);
// Check if an item was selected
if (ui_state->body_list_active >= 0 && ui_state->body_list_active != previous_active) {
@ -150,8 +165,6 @@ void render_body_list_ui(SimulationState* sim, RenderState* render_state, UIStat
}
}
}
free(list_text);
}
// Render body information UI panel
@ -381,25 +394,45 @@ void render_maneuver_list_ui(SimulationState* sim, RenderState* render_state, UI
return;
}
int buffer_size = craft_maneuver_count * (64 + 10 + 1) + 1;
char* maneuver_list_text = (char*)malloc(buffer_size);
if (!maneuver_list_text) return;
maneuver_list_text[0] = '\0';
int offset = 0;
int maneuver_indices[craft_maneuver_count];
int maneuver_index_count = 0;
for (int i = 0; i < sim->maneuver_count; i++) {
if (sim->maneuvers[i].craft_index == ui_state->selected_craft_index) {
maneuver_indices[maneuver_index_count++] = i;
if (offset > 0) {
offset += snprintf(maneuver_list_text + offset, buffer_size - offset, ";");
}
}
// Check if buffer needs rebuilding
bool needs_rebuild = (ui_state->sim_version != sim->version) || (ui_state->maneuver_list_buffer == NULL);
if (needs_rebuild) {
int buffer_size = craft_maneuver_count * (64 + 10 + 1) + 1;
if (ui_state->maneuver_list_buffer == NULL || ui_state->maneuver_list_buffer_size < buffer_size) {
if (ui_state->maneuver_list_buffer != NULL) {
free(ui_state->maneuver_list_buffer);
}
ui_state->maneuver_list_buffer = (char*)malloc(buffer_size);
if (!ui_state->maneuver_list_buffer) return;
ui_state->maneuver_list_buffer_size = buffer_size;
}
ui_state->maneuver_list_buffer[0] = '\0';
int offset = 0;
for (int i = 0; i < sim->maneuver_count; i++) {
if (sim->maneuvers[i].craft_index == ui_state->selected_craft_index) {
if (offset > 0) {
offset += snprintf(ui_state->maneuver_list_buffer + offset, ui_state->maneuver_list_buffer_size - offset, ";");
}
const char* status_char = sim->maneuvers[i].executed ? "[DONE]" : "[PENDING]";
offset += snprintf(ui_state->maneuver_list_buffer + offset, ui_state->maneuver_list_buffer_size - offset, "%s %s",
status_char, sim->maneuvers[i].name);
}
const char* status_char = sim->maneuvers[i].executed ? "[DONE]" : "[PENDING]";
offset += snprintf(maneuver_list_text + offset, buffer_size - offset, "%s %s",
status_char, sim->maneuvers[i].name);
}
ui_state->sim_version = sim->version;
}
Rectangle list_bounds = {
@ -410,7 +443,7 @@ void render_maneuver_list_ui(SimulationState* sim, RenderState* render_state, UI
};
int previous_active = ui_state->maneuver_list_active;
GuiListView(list_bounds, maneuver_list_text, &ui_state->maneuver_list_scroll, &ui_state->maneuver_list_active);
GuiListView(list_bounds, ui_state->maneuver_list_buffer, &ui_state->maneuver_list_scroll, &ui_state->maneuver_list_active);
if (ui_state->maneuver_list_active >= 0 && ui_state->maneuver_list_active != previous_active) {
if (ui_state->maneuver_list_active >= 0 && ui_state->maneuver_list_active < maneuver_index_count) {
@ -527,8 +560,6 @@ void render_maneuver_list_ui(SimulationState* sim, RenderState* render_state, UI
}
}
}
free(maneuver_list_text);
}
void render_maneuver_create_tab(SimulationState* sim, UIState* ui_state, int x, int y, int width, int height) {
@ -713,6 +744,50 @@ void render_maneuver_hohmann_tab(SimulationState* sim, UIState* ui_state, int x,
}
}
if (ui_state->sim_version != sim->version) {
int craft_buffer_size = sim->craft_count * 64 + 1;
if (ui_state->craft_list_buffer == NULL || ui_state->craft_list_buffer_size < craft_buffer_size) {
if (ui_state->craft_list_buffer != NULL) {
free(ui_state->craft_list_buffer);
}
ui_state->craft_list_buffer = (char*)malloc(craft_buffer_size);
if (!ui_state->craft_list_buffer) return;
ui_state->craft_list_buffer_size = craft_buffer_size;
}
ui_state->craft_list_buffer[0] = '\0';
int offset = 0;
for (int i = 0; i < sim->craft_count; i++) {
if (i > 0) {
offset += snprintf(ui_state->craft_list_buffer + offset, ui_state->craft_list_buffer_size - offset, ";");
}
offset += snprintf(ui_state->craft_list_buffer + offset, ui_state->craft_list_buffer_size - offset, "%s", sim->spacecraft[i].name);
}
int body_buffer_size = sim->body_count * 64 + 1;
if (ui_state->body_dropdown_buffer == NULL || ui_state->body_dropdown_buffer_size < body_buffer_size) {
if (ui_state->body_dropdown_buffer != NULL) {
free(ui_state->body_dropdown_buffer);
}
ui_state->body_dropdown_buffer = (char*)malloc(body_buffer_size);
if (!ui_state->body_dropdown_buffer) return;
ui_state->body_dropdown_buffer_size = body_buffer_size;
}
ui_state->body_dropdown_buffer[0] = '\0';
offset = 0;
for (int i = 0; i < sim->body_count; i++) {
if (i > 0) {
offset += snprintf(ui_state->body_dropdown_buffer + offset, ui_state->body_dropdown_buffer_size - offset, ";");
}
offset += snprintf(ui_state->body_dropdown_buffer + offset, ui_state->body_dropdown_buffer_size - offset, "%s", sim->bodies[i].name);
}
ui_state->sim_version = sim->version;
}
GuiLabel({(float)x, (float)current_y, (float)width, 25}, "Calculate optimal Hohmann transfer between orbits");
current_y += 30;
@ -721,25 +796,11 @@ void render_maneuver_hohmann_tab(SimulationState* sim, UIState* ui_state, int x,
if (sim->craft_count > 0) {
static bool edit_mode_spacecraft = false;
int craft_buffer_size = sim->craft_count * 64 + 1;
char* craft_list = (char*)malloc(craft_buffer_size);
if (craft_list) {
craft_list[0] = '\0';
int offset = 0;
for (int i = 0; i < sim->craft_count; i++) {
if (i > 0) {
offset += snprintf(craft_list + offset, craft_buffer_size - offset, ";");
}
offset += snprintf(craft_list + offset, craft_buffer_size - offset, "%s", sim->spacecraft[i].name);
}
if (GuiDropdownBox({(float)x + 120, (float)(current_y - 35), (float)(width - 130), 25},
craft_list, &ui_state->maneuver_dialog.craft_index, edit_mode_spacecraft)) {
edit_mode_spacecraft = !edit_mode_spacecraft;
}
free(craft_list);
if (edit_mode_spacecraft) return;
if (GuiDropdownBox({(float)x + 120, (float)(current_y - 35), (float)(width - 130), 25},
ui_state->craft_list_buffer, &ui_state->maneuver_dialog.craft_index, edit_mode_spacecraft)) {
edit_mode_spacecraft = !edit_mode_spacecraft;
}
if (edit_mode_spacecraft) return;
}
current_y += 35;
@ -748,25 +809,11 @@ void render_maneuver_hohmann_tab(SimulationState* sim, UIState* ui_state, int x,
if (sim->body_count > 0) {
static bool edit_mode_transfer_parent = false;
int body_buffer_size = sim->body_count * 64 + 1;
char* body_list = (char*)malloc(body_buffer_size);
if (body_list) {
body_list[0] = '\0';
int offset = 0;
for (int i = 0; i < sim->body_count; i++) {
if (i > 0) {
offset += snprintf(body_list + offset, body_buffer_size - offset, ";");
}
offset += snprintf(body_list + offset, body_buffer_size - offset, "%s", sim->bodies[i].name);
}
if (GuiDropdownBox({(float)x + 120, (float)(current_y - 35), (float)(width - 130), 25},
body_list, &ui_state->maneuver_dialog.transfer_body_index, edit_mode_transfer_parent)) {
edit_mode_transfer_parent = !edit_mode_transfer_parent;
}
free(body_list);
if (edit_mode_transfer_parent) return;
if (GuiDropdownBox({(float)x + 120, (float)(current_y - 35), (float)(width - 130), 25},
ui_state->body_dropdown_buffer, &ui_state->maneuver_dialog.transfer_body_index, edit_mode_transfer_parent)) {
edit_mode_transfer_parent = !edit_mode_transfer_parent;
}
if (edit_mode_transfer_parent) return;
}
current_y += 35;
@ -775,25 +822,11 @@ void render_maneuver_hohmann_tab(SimulationState* sim, UIState* ui_state, int x,
if (sim->body_count > 0) {
static bool edit_mode_current_body = false;
int body_buffer_size = sim->body_count * 64 + 1;
char* body_list = (char*)malloc(body_buffer_size);
if (body_list) {
body_list[0] = '\0';
int offset = 0;
for (int i = 0; i < sim->body_count; i++) {
if (i > 0) {
offset += snprintf(body_list + offset, body_buffer_size - offset, ";");
}
offset += snprintf(body_list + offset, body_buffer_size - offset, "%s", sim->bodies[i].name);
}
if (GuiDropdownBox({(float)x + 120, (float)(current_y - 35), (float)(width - 130), 25},
body_list, &ui_state->maneuver_dialog.current_body_index, edit_mode_current_body)) {
edit_mode_current_body = !edit_mode_current_body;
}
free(body_list);
if (edit_mode_current_body) return;
if (GuiDropdownBox({(float)x + 120, (float)(current_y - 35), (float)(width - 130), 25},
ui_state->body_dropdown_buffer, &ui_state->maneuver_dialog.current_body_index, edit_mode_current_body)) {
edit_mode_current_body = !edit_mode_current_body;
}
if (edit_mode_current_body) return;
}
current_y += 35;
@ -802,25 +835,11 @@ void render_maneuver_hohmann_tab(SimulationState* sim, UIState* ui_state, int x,
if (sim->body_count > 0) {
static bool edit_mode_target_body = false;
int body_buffer_size = sim->body_count * 64 + 1;
char* body_list = (char*)malloc(body_buffer_size);
if (body_list) {
body_list[0] = '\0';
int offset = 0;
for (int i = 0; i < sim->body_count; i++) {
if (i > 0) {
offset += snprintf(body_list + offset, body_buffer_size - offset, ";");
}
offset += snprintf(body_list + offset, body_buffer_size - offset, "%s", sim->bodies[i].name);
}
if (GuiDropdownBox({(float)x + 120, (float)(current_y - 35), (float)(width - 130), 25},
body_list, &ui_state->maneuver_dialog.target_body_index, edit_mode_target_body)) {
edit_mode_target_body = !edit_mode_target_body;
}
free(body_list);
if (edit_mode_target_body) return;
if (GuiDropdownBox({(float)x + 120, (float)(current_y - 35), (float)(width - 130), 25},
ui_state->body_dropdown_buffer, &ui_state->maneuver_dialog.target_body_index, edit_mode_target_body)) {
edit_mode_target_body = !edit_mode_target_body;
}
if (edit_mode_target_body) return;
}
current_y += 35;
@ -1409,3 +1428,41 @@ void delete_maneuver_from_dialog(SimulationState* sim, UIState* ui_state) {
ui_state->maneuver_dialog.open = false;
}
}
void ui_state_init_buffers(UIState* ui_state) {
ui_state->sim_version = 0;
ui_state->body_list_buffer_size = 0;
ui_state->body_list_buffer = NULL;
ui_state->craft_list_buffer_size = 0;
ui_state->craft_list_buffer = NULL;
ui_state->body_dropdown_buffer_size = 0;
ui_state->body_dropdown_buffer = NULL;
ui_state->maneuver_list_buffer_size = 0;
ui_state->maneuver_list_buffer = NULL;
}
void ui_state_free_buffers(UIState* ui_state) {
if (ui_state->body_list_buffer != NULL) {
free(ui_state->body_list_buffer);
ui_state->body_list_buffer = NULL;
}
ui_state->body_list_buffer_size = 0;
if (ui_state->craft_list_buffer != NULL) {
free(ui_state->craft_list_buffer);
ui_state->craft_list_buffer = NULL;
}
ui_state->craft_list_buffer_size = 0;
if (ui_state->body_dropdown_buffer != NULL) {
free(ui_state->body_dropdown_buffer);
ui_state->body_dropdown_buffer = NULL;
}
ui_state->body_dropdown_buffer_size = 0;
if (ui_state->maneuver_list_buffer != NULL) {
free(ui_state->maneuver_list_buffer);
ui_state->maneuver_list_buffer = NULL;
}
ui_state->maneuver_list_buffer_size = 0;
}

12
src/ui_renderer.h

@ -50,6 +50,16 @@ struct UIState {
int maneuver_list_active;
int maneuver_list_scroll;
int selected_maneuver_index;
int sim_version;
int body_list_buffer_size;
char* body_list_buffer;
int craft_list_buffer_size;
char* craft_list_buffer;
int body_dropdown_buffer_size;
char* body_dropdown_buffer;
int maneuver_list_buffer_size;
char* maneuver_list_buffer;
};
void gui_init();
@ -73,5 +83,7 @@ void calculate_hohmann_for_dialog(SimulationState* sim, UIState* ui_state);
void create_hohmann_burns(SimulationState* sim, UIState* ui_state, bool create_both_burns);
void load_maneuver_into_dialog(SimulationState* sim, UIState* ui_state, int maneuver_index);
void delete_maneuver_from_dialog(SimulationState* sim, UIState* ui_state);
void ui_state_init_buffers(UIState* ui_state);
void ui_state_free_buffers(UIState* ui_state);
#endif

Loading…
Cancel
Save