Browse Source

Add raygui integration and UI functionality for body selection

- Add raygui as git submodule in ext/raygui/
- Update Makefile to include raygui headers
- Extend RenderState with UI fields (selected_body_index, show_body_list, show_body_info)
- Implement render_body_list_ui() for scrollable body list panel
- Implement render_body_info_ui() for detailed body information panel
- Add 'B' key toggle for body list panel
- Integrate UI rendering into main render loop
- Initialize UI state in main()
main
cinnaboot 6 months ago
parent
commit
32e0bf2512
  1. 3
      .gitmodules
  2. 2
      Makefile
  3. 1
      ext/raygui
  4. 6
      src/main.cpp
  5. 143
      src/renderer.cpp
  6. 7
      src/renderer.h

3
.gitmodules vendored

@ -4,3 +4,6 @@
[submodule "ext/tomlc17"]
path = ext/tomlc17
url = https://github.com/cktan/tomlc17
[submodule "ext/raygui"]
path = ext/raygui
url = https://github.com/raysan5/raygui.git

2
Makefile

@ -1,6 +1,6 @@
# Compiler and flags
CXX = g++
CXXFLAGS = -Wall -Wextra -g -ggdb3 -std=c++14 -I./src -isystem./ext/raylib/src -I./ext/tomlc17/src
CXXFLAGS = -Wall -Wextra -g -ggdb3 -std=c++14 -I./src -isystem./ext/raylib/src -I./ext/tomlc17/src -I./ext/raygui/src
LDFLAGS = -L./ext/raylib/src -lraylib -lm -lpthread -ldl -lrt -lX11
# Directories

1
ext/raygui

@ -0,0 +1 @@
Subproject commit 9a1c183d8539e2470635b22f92bdaefaf5218aaa

6
src/main.cpp

@ -35,6 +35,11 @@ void run_gui_simulation(SimulationState* sim) {
RenderState render_state;
setup_camera(&render_state);
// Initialize UI state
render_state.selected_body_index = -1; // No selection initially
render_state.show_body_list = false;
render_state.show_body_info = false;
bool paused = false;
double speed_multiplier = 1.0;
@ -46,6 +51,7 @@ void run_gui_simulation(SimulationState* sim) {
printf(" Space: Pause/Resume\n");
printf(" +/-: Speed up/slow down simulation\n");
printf(" I: Toggle info display\n");
printf(" B: Toggle body list\n");
printf(" ESC: Quit\n\n");
while (!WindowShouldClose()) {

143
src/renderer.cpp

@ -3,6 +3,10 @@
#include <cmath>
#include <cstdio>
// raygui implementation (header-only library)
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
// Initialize raylib window
void init_renderer(int width, int height, const char* title) {
InitWindow(width, height, title);
@ -68,6 +72,11 @@ void update_camera(RenderState* render_state) {
if (IsKeyPressed(KEY_I)) {
render_state->show_info = !render_state->show_info;
}
// Toggle body list with B key
if (IsKeyPressed(KEY_B)) {
render_state->show_body_list = !render_state->show_body_list;
}
}
// Transform from simulation coordinates (XY plane) to render coordinates (XZ plane)
@ -316,6 +325,10 @@ void render_simulation(SimulationState* sim, RenderState* render_state) {
render_info(sim, "solar_system.txt");
}
// Render UI panels
render_body_list_ui(sim, render_state);
render_body_info_ui(sim, render_state);
EndDrawing();
}
@ -350,3 +363,133 @@ void render_info(SimulationState* sim, const char* config_name) {
DrawText(" I: Toggle info", 10, 210, 14, LIGHTGRAY);
DrawText(" ESC: Quit", 10, 230, 14, LIGHTGRAY);
}
// Render body list UI panel
void render_body_list_ui(SimulationState* sim, RenderState* render_state) {
if (!render_state->show_body_list) return;
// Panel dimensions
int panel_width = 200;
int panel_height = 400;
int panel_x = 10;
int panel_y = 10;
Rectangle panel_bounds = { (float)panel_x, (float)panel_y, (float)panel_width, (float)panel_height };
// Create body list for raygui
const char** body_names = (const char**)malloc(sim->body_count * sizeof(char*));
if (!body_names) return;
for (int i = 0; i < sim->body_count; i++) {
body_names[i] = sim->bodies[i].name;
}
// Draw window
if (GuiWindowBox(panel_bounds, "Bodies")) {
render_state->show_body_list = false;
}
// Draw list view (inside window, leave space for title bar)
Rectangle list_bounds = {
(float)panel_x + 4,
(float)panel_y + 25,
(float)panel_width - 8,
(float)panel_height - 29
};
int focus = 0;
int active = 0;
if (render_state->selected_body_index >= 0 && render_state->selected_body_index < sim->body_count) {
focus = render_state->selected_body_index; // 0-based indexing for scroll
active = 1; // Mark as active
}
int result = GuiListView(list_bounds, (const char*)body_names, &focus, &active);
if (result >= 0 && result < sim->body_count) {
render_state->selected_body_index = result;
render_state->show_body_info = true;
}
free(body_names);
}
// Render body information UI panel
void render_body_info_ui(SimulationState* sim, RenderState* render_state) {
if (!render_state->show_body_info || render_state->selected_body_index < 0 ||
render_state->selected_body_index >= sim->body_count) return;
// Panel dimensions
int panel_width = 250;
int panel_height = 300;
int panel_x = GetScreenWidth() - panel_width - 10;
int panel_y = 10;
Rectangle panel_bounds = { (float)panel_x, (float)panel_y, (float)panel_width, (float)panel_height };
CelestialBody* body = &sim->bodies[render_state->selected_body_index];
// Draw window
if (GuiWindowBox(panel_bounds, body->name)) {
render_state->show_body_info = false;
}
// Prepare info text
char info_text[1024];
char temp_buffer[256];
snprintf(info_text, sizeof(info_text), "Name: %s", body->name);
snprintf(temp_buffer, sizeof(temp_buffer), "Mass: %.2e kg", body->mass);
strcat(info_text, "\n");
strcat(info_text, temp_buffer);
snprintf(temp_buffer, sizeof(temp_buffer), "Radius: %.2e m", body->radius);
strcat(info_text, "\n");
strcat(info_text, temp_buffer);
// Position
snprintf(temp_buffer, sizeof(temp_buffer), "Position: (%.2e, %.2e, %.2e)",
body->position.x, body->position.y, body->position.z);
strcat(info_text, "\n");
strcat(info_text, temp_buffer);
// Velocity
double vel_mag = vec3_magnitude(body->velocity);
snprintf(temp_buffer, sizeof(temp_buffer), "Velocity: %.2f m/s", vel_mag);
strcat(info_text, "\n");
strcat(info_text, temp_buffer);
// Orbital elements
snprintf(temp_buffer, sizeof(temp_buffer), "Eccentricity: %.3f", body->eccentricity);
strcat(info_text, "\n");
strcat(info_text, temp_buffer);
snprintf(temp_buffer, sizeof(temp_buffer), "Semi-major axis: %.2e m", body->semi_major_axis);
strcat(info_text, "\n");
strcat(info_text, temp_buffer);
// Parent body
if (body->parent_index >= 0 && body->parent_index < sim->body_count) {
snprintf(temp_buffer, sizeof(temp_buffer), "Parent: %s", sim->bodies[body->parent_index].name);
} else {
snprintf(temp_buffer, sizeof(temp_buffer), "Parent: None");
}
strcat(info_text, "\n");
strcat(info_text, temp_buffer);
// SOI
snprintf(temp_buffer, sizeof(temp_buffer), "SOI radius: %.2e m", body->soi_radius);
strcat(info_text, "\n");
strcat(info_text, temp_buffer);
// Draw info text (inside window, leave space for title bar)
Rectangle text_bounds = {
(float)panel_x + 8,
(float)panel_y + 25,
(float)panel_width - 16,
(float)panel_height - 29
};
GuiLabel(text_bounds, info_text);
}

7
src/renderer.h

@ -10,6 +10,9 @@ struct RenderState {
double distance_scale; // Scale factor for distances
double size_scale; // Scale factor for body sizes
bool show_info; // Display simulation info
int selected_body_index; // -1 = no selection
bool show_body_list; // Toggle for list panel
bool show_body_info; // Toggle for info panel
};
// Renderer initialization and cleanup
@ -26,6 +29,10 @@ void render_body(CelestialBody* body, RenderState* render_state);
void render_simulation(SimulationState* sim, RenderState* render_state);
void render_info(SimulationState* sim, const char* config_name);
// UI rendering functions
void render_body_list_ui(SimulationState* sim, RenderState* render_state);
void render_body_info_ui(SimulationState* sim, RenderState* render_state);
// Scaling functions
Vector3 scale_position(Vec3 pos, double scale);
float scale_radius(double radius, double scale);

Loading…
Cancel
Save