@ -32,7 +32,6 @@ void setup_camera(RenderState* render_state) {
// Set scaling factors (same scale for distances and sizes)
// Set scaling factors (same scale for distances and sizes)
render_state - > distance_scale = 1e-9 ; // Meters to scaled units (1 unit = 1 billion meters)
render_state - > distance_scale = 1e-9 ; // Meters to scaled units (1 unit = 1 billion meters)
render_state - > size_scale = 1e-9 ; // Same scale for body sizes (minimum size still applies)
render_state - > size_scale = 1e-9 ; // Same scale for body sizes (minimum size still applies)
render_state - > show_info = true ;
}
}
// Update camera with keyboard/mouse controls
// Update camera with keyboard/mouse controls
@ -137,26 +136,6 @@ void update_camera(RenderState* render_state, SimulationState* sim) {
}
}
}
}
// Toggle info display with I key
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 ;
}
// Toggle camera follow with F key
if ( IsKeyPressed ( KEY_F ) ) {
if ( render_state - > selected_body_index > = 0 ) {
render_state - > camera_follow_body = ! render_state - > camera_follow_body ;
printf ( " Camera follow: %s \n " , render_state - > camera_follow_body ? " enabled " : " disabled " ) ;
} else {
render_state - > camera_follow_body = false ;
}
}
// Store previous follow state
// Store previous follow state
render_state - > was_following_body = render_state - > camera_follow_body ;
render_state - > was_following_body = render_state - > camera_follow_body ;
}
}
@ -398,12 +377,8 @@ void render_simulation(SimulationState* sim, RenderState* render_state) {
EndMode3D ( ) ;
EndMode3D ( ) ;
// Render 2D info overlay
// Render UI panels (always shown)
if ( render_state - > show_info ) {
render_info ( sim , " solar_system.txt " ) ;
render_info ( sim , " solar_system.txt " ) ;
}
// Render UI panels
render_body_list_ui ( sim , render_state ) ;
render_body_list_ui ( sim , render_state ) ;
render_body_info_ui ( sim , render_state ) ;
render_body_info_ui ( sim , render_state ) ;
@ -412,40 +387,59 @@ void render_simulation(SimulationState* sim, RenderState* render_state) {
// Render simulation information overlay
// Render simulation information overlay
void render_info ( SimulationState * sim , const char * config_name ) {
void render_info ( SimulationState * sim , const char * config_name ) {
DrawText ( " Orbital Mechanics Simulation " , 10 , 10 , 20 , WHITE ) ;
// Panel dimensions
int panel_width = 200 ;
int panel_height = 280 ;
int panel_x = 10 ;
int panel_y = GetScreenHeight ( ) - panel_height - 10 ;
char buffer [ 256 ] ;
Rectangle panel_bounds = { ( float ) panel_x , ( float ) panel_y , ( float ) panel_width , ( float ) panel_height } ;
// Draw window
if ( GuiWindowBox ( panel_bounds , " Info " ) ) {
// Window box close button doesn't close this panel
}
// Prepare info text
char info_text [ 1024 ] ;
char temp_buffer [ 256 ] ;
int offset = 0 ;
snprintf ( info_text , sizeof ( info_text ) , " Orbital Mechanics Simulation \n \n " ) ;
// Simulation time (in days)
// Simulation time (in days)
double days = sim - > time / 86400.0 ; // seconds to days
double days = sim - > time / 86400.0 ; // seconds to days
snprintf ( buffer , sizeof ( buffer ) , " Time: %.2f days " , days ) ;
snprintf ( temp_ buffer, sizeof ( temp_ buffer) , " Time: %.2f days \n " , days ) ;
DrawText ( buffer , 10 , 40 , 16 , LIGHTGRAY ) ;
strcat ( info_text , temp_buffer ) ;
// Body count
// Body count
snprintf ( buffer , sizeof ( buffer ) , " Bodies: %d " , sim - > body_count ) ;
snprintf ( temp_buffer , sizeof ( temp_buffer ) , " Bodies: %d \n " , sim - > body_count ) ;
DrawText ( buffer , 10 , 60 , 16 , LIGHTGRAY ) ;
strcat ( info_text , temp_buffer ) ;
// Config name
snprintf ( buffer , sizeof ( buffer ) , " Config: %s " , config_name ) ;
DrawText ( buffer , 10 , 80 , 16 , LIGHTGRAY ) ;
// FPS
// FPS
snprintf ( buffer , sizeof ( buffer ) , " FPS: %d " , GetFPS ( ) ) ;
snprintf ( temp_buffer , sizeof ( temp_buffer ) , " FPS: %d \n \n " , GetFPS ( ) ) ;
DrawText ( buffer , 10 , 100 , 16 , LIGHTGRAY ) ;
strcat ( info_text , temp_buffer ) ;
// Controls
// Controls
DrawText ( " Controls: " , 10 , 130 , 16 , YELLOW ) ;
strcat ( info_text , " Controls: \n " ) ;
DrawText ( " Arrows: Rotate/Zoom camera " , 10 , 150 , 14 , LIGHTGRAY ) ;
strcat ( info_text , " Arrows: Rotate/Zoom \n " ) ;
DrawText ( " Space: Pause/Resume " , 10 , 170 , 14 , LIGHTGRAY ) ;
strcat ( info_text , " Space: Pause/Resume \n " ) ;
DrawText ( " +/-: Speed up/slow down " , 10 , 190 , 14 , LIGHTGRAY ) ;
strcat ( info_text , " +/-: Speed control \n " ) ;
DrawText ( " I: Toggle info " , 10 , 210 , 14 , LIGHTGRAY ) ;
strcat ( info_text , " ESC: Quit \n " ) ;
DrawText ( " ESC: Quit " , 10 , 230 , 14 , LIGHTGRAY ) ;
// 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 ) ;
}
}
// Render body list UI panel
// Render body list UI panel
void render_body_list_ui ( SimulationState * sim , RenderState * render_state ) {
void render_body_list_ui ( SimulationState * sim , RenderState * render_state ) {
if ( ! render_state - > show_body_list ) return ;
// Panel dimensions
// Panel dimensions
int panel_width = 200 ;
int panel_width = 200 ;
int panel_height = 400 ;
int panel_height = 400 ;
@ -469,10 +463,8 @@ void render_body_list_ui(SimulationState* sim, RenderState* render_state) {
offset + = snprintf ( body_list_text + offset , buffer_size - offset , " %s " , sim - > bodies [ i ] . name ) ;
offset + = snprintf ( body_list_text + offset , buffer_size - offset , " %s " , sim - > bodies [ i ] . name ) ;
}
}
// Draw window
// Draw window (no close button - panels always shown)
if ( GuiWindowBox ( panel_bounds , " Bodies " ) ) {
GuiWindowBox ( panel_bounds , " Bodies " ) ;
render_state - > show_body_list = false ;
}
// Draw list view (inside window, leave space for title bar)
// Draw list view (inside window, leave space for title bar)
Rectangle list_bounds = {
Rectangle list_bounds = {
@ -489,7 +481,9 @@ void render_body_list_ui(SimulationState* sim, RenderState* render_state) {
if ( render_state - > body_list_active > = 0 & & render_state - > body_list_active < sim - > body_count & &
if ( render_state - > body_list_active > = 0 & & render_state - > body_list_active < sim - > body_count & &
render_state - > body_list_active ! = previous_active ) {
render_state - > body_list_active ! = previous_active ) {
render_state - > selected_body_index = render_state - > body_list_active ;
render_state - > selected_body_index = render_state - > body_list_active ;
render_state - > show_body_info = true ;
// Enable camera follow when body is selected
render_state - > camera_follow_body = true ;
printf ( " Camera follow enabled for: %s \n " , sim - > bodies [ render_state - > selected_body_index ] . name ) ;
}
}
free ( body_list_text ) ;
free ( body_list_text ) ;
@ -497,8 +491,17 @@ void render_body_list_ui(SimulationState* sim, RenderState* render_state) {
// Render body information UI panel
// Render body information UI panel
void render_body_info_ui ( SimulationState * sim , RenderState * render_state ) {
void render_body_info_ui ( SimulationState * sim , RenderState * render_state ) {
if ( ! render_state - > show_body_info | | render_state - > selected_body_index < 0 | |
if ( render_state - > selected_body_index < 0 | | render_state - > selected_body_index > = sim - > body_count ) {
render_state - > selected_body_index > = sim - > body_count ) return ;
// No body selected - render empty panel
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 } ;
GuiWindowBox ( panel_bounds , " Info " ) ;
return ;
}
// Panel dimensions
// Panel dimensions
int panel_width = 250 ;
int panel_width = 250 ;
@ -510,10 +513,8 @@ void render_body_info_ui(SimulationState* sim, RenderState* render_state) {
CelestialBody * body = & sim - > bodies [ render_state - > selected_body_index ] ;
CelestialBody * body = & sim - > bodies [ render_state - > selected_body_index ] ;
// Draw window
// Draw window (no close button - panels always shown)
if ( GuiWindowBox ( panel_bounds , body - > name ) ) {
GuiWindowBox ( panel_bounds , body - > name ) ;
render_state - > show_body_info = false ;
}
// Prepare info text
// Prepare info text
char info_text [ 1024 ] ;
char info_text [ 1024 ] ;