update
This commit is contained in:
parent
432e5a737a
commit
ad4c3ada92
137
src/main.rs
137
src/main.rs
@ -1,12 +1,15 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
core_pipeline::{bloom::Bloom, tonemapping::Tonemapping},
|
core_pipeline::tonemapping::Tonemapping,
|
||||||
input::mouse::{MouseScrollUnit, MouseWheel},
|
input::mouse::{MouseScrollUnit, MouseWheel},
|
||||||
math::DVec3,
|
math::DVec3,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
window::{WindowMode, WindowResolution},
|
window::WindowResolution,
|
||||||
};
|
};
|
||||||
use bevy_inspector_egui::{bevy_egui::EguiPlugin, quick::WorldInspectorPlugin};
|
use bevy_inspector_egui::{
|
||||||
use iyes_perf_ui::{PerfUiPlugin, prelude::PerfUiAllEntries};
|
bevy_egui::{EguiContextSettings, EguiPlugin},
|
||||||
|
quick::WorldInspectorPlugin,
|
||||||
|
};
|
||||||
|
use iyes_perf_ui::{PerfUiPlugin, prelude::*};
|
||||||
|
|
||||||
// Scaling factor to convert AU to game units
|
// Scaling factor to convert AU to game units
|
||||||
// Neptune is approximately 30.1 astronomical units (AU) from the Sun
|
// Neptune is approximately 30.1 astronomical units (AU) from the Sun
|
||||||
@ -76,6 +79,14 @@ struct CameraFollow {
|
|||||||
distance: f32, // Current zoom distance from target
|
distance: f32, // Current zoom distance from target
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resource to manage UI scaling across different resolutions
|
||||||
|
#[derive(Resource)]
|
||||||
|
struct UiScale {
|
||||||
|
scale_factor: f32,
|
||||||
|
base_font_size: f32,
|
||||||
|
current_font_size: f32,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct SolarRenderingPlugin;
|
pub struct SolarRenderingPlugin;
|
||||||
|
|
||||||
impl Plugin for SolarRenderingPlugin {
|
impl Plugin for SolarRenderingPlugin {
|
||||||
@ -84,6 +95,11 @@ impl Plugin for SolarRenderingPlugin {
|
|||||||
target: None,
|
target: None,
|
||||||
distance: 10.0,
|
distance: 10.0,
|
||||||
})
|
})
|
||||||
|
.insert_resource(UiScale {
|
||||||
|
scale_factor: 1.0,
|
||||||
|
base_font_size: 16.0,
|
||||||
|
current_font_size: 16.0,
|
||||||
|
})
|
||||||
.add_systems(Startup, (setup_rendering, setup_ui))
|
.add_systems(Startup, (setup_rendering, setup_ui))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
FixedPostUpdate,
|
FixedPostUpdate,
|
||||||
@ -95,7 +111,16 @@ impl Plugin for SolarRenderingPlugin {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_systems(PostUpdate, update_label_positions)
|
.add_systems(PostUpdate, update_label_positions)
|
||||||
.add_systems(Update, (handle_label_clicks, handle_scroll_zoom));
|
.add_systems(
|
||||||
|
Update,
|
||||||
|
(
|
||||||
|
handle_label_clicks,
|
||||||
|
handle_scroll_zoom,
|
||||||
|
handle_speed_controls,
|
||||||
|
update_ui_scale,
|
||||||
|
update_label_font_sizes.after(update_ui_scale),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,6 +231,7 @@ fn sync_name_labels(
|
|||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
objects_with_names: Query<(Entity, &Name, &Position), Changed<Name>>,
|
objects_with_names: Query<(Entity, &Name, &Position), Changed<Name>>,
|
||||||
existing_labels: Query<&ObjectLabel>,
|
existing_labels: Query<&ObjectLabel>,
|
||||||
|
ui_scale: Res<UiScale>,
|
||||||
) {
|
) {
|
||||||
for (entity, name, _position) in objects_with_names.iter() {
|
for (entity, name, _position) in objects_with_names.iter() {
|
||||||
// Check if label already exists for this entity
|
// Check if label already exists for this entity
|
||||||
@ -214,12 +240,12 @@ fn sync_name_labels(
|
|||||||
.any(|label| label.target_entity == entity);
|
.any(|label| label.target_entity == entity);
|
||||||
|
|
||||||
if !has_label {
|
if !has_label {
|
||||||
// Create new label
|
// Create new label with scaled font size
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
Text::new(name.0.0.clone()),
|
Text::new(name.0.0.clone()),
|
||||||
TextColor(Color::WHITE),
|
TextColor(Color::WHITE),
|
||||||
TextFont {
|
TextFont {
|
||||||
font_size: 16.0,
|
font_size: ui_scale.current_font_size,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
Node {
|
Node {
|
||||||
@ -242,6 +268,7 @@ fn update_label_positions(
|
|||||||
mut label_query: Query<(&mut Node, &ObjectLabel, &mut Text), With<ObjectLabel>>,
|
mut label_query: Query<(&mut Node, &ObjectLabel, &mut Text), With<ObjectLabel>>,
|
||||||
objects_query: Query<(&GlobalTransform, &Name, &Radius)>,
|
objects_query: Query<(&GlobalTransform, &Name, &Radius)>,
|
||||||
camera_query: Query<(&Camera, &GlobalTransform)>,
|
camera_query: Query<(&Camera, &GlobalTransform)>,
|
||||||
|
ui_scale: Res<UiScale>,
|
||||||
) {
|
) {
|
||||||
let Ok((camera, camera_transform)) = camera_query.single() else {
|
let Ok((camera, camera_transform)) = camera_query.single() else {
|
||||||
return;
|
return;
|
||||||
@ -251,9 +278,12 @@ fn update_label_positions(
|
|||||||
if let Ok((global_transform, name, _radius)) = objects_query.get(label.target_entity) {
|
if let Ok((global_transform, name, _radius)) = objects_query.get(label.target_entity) {
|
||||||
let world_pos = global_transform.translation();
|
let world_pos = global_transform.translation();
|
||||||
if let Ok(screen_pos) = camera.world_to_viewport(camera_transform, world_pos) {
|
if let Ok(screen_pos) = camera.world_to_viewport(camera_transform, world_pos) {
|
||||||
|
// Apply scale factor to label offset to maintain relative positioning
|
||||||
|
let scaled_offset = 10.0 * ui_scale.scale_factor;
|
||||||
|
|
||||||
// Position the label on screen, offset slightly to avoid overlapping the object
|
// Position the label on screen, offset slightly to avoid overlapping the object
|
||||||
node.left = Val::Px(screen_pos.x);
|
node.left = Val::Px(screen_pos.x + scaled_offset);
|
||||||
node.top = Val::Px(screen_pos.y);
|
node.top = Val::Px(screen_pos.y - scaled_offset);
|
||||||
|
|
||||||
// Update text in case name changed
|
// Update text in case name changed
|
||||||
text.0 = name.0.0.clone();
|
text.0 = name.0.0.clone();
|
||||||
@ -345,6 +375,89 @@ fn handle_scroll_zoom(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_speed_controls(
|
||||||
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
|
mut time: ResMut<Time<Virtual>>,
|
||||||
|
) {
|
||||||
|
// Pause/Unpause with SPACE
|
||||||
|
if keyboard_input.just_pressed(KeyCode::Space) {
|
||||||
|
if time.is_paused() {
|
||||||
|
time.unpause();
|
||||||
|
println!("Simulation RESUMED (Speed: {}x)", time.relative_speed());
|
||||||
|
} else {
|
||||||
|
time.pause();
|
||||||
|
println!("Simulation PAUSED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Speed up with + or = key (double current speed, max 64x)
|
||||||
|
if keyboard_input.just_pressed(KeyCode::Equal)
|
||||||
|
|| keyboard_input.just_pressed(KeyCode::NumpadAdd)
|
||||||
|
{
|
||||||
|
if !time.is_paused() {
|
||||||
|
let current_speed = time.relative_speed();
|
||||||
|
let new_speed = (current_speed * 2.0).min(64.0);
|
||||||
|
time.set_relative_speed(new_speed);
|
||||||
|
println!("Speed: {}x", new_speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Speed down with - key (halve current speed, min 1.0x)
|
||||||
|
if keyboard_input.just_pressed(KeyCode::Minus)
|
||||||
|
|| keyboard_input.just_pressed(KeyCode::NumpadSubtract)
|
||||||
|
{
|
||||||
|
if !time.is_paused() {
|
||||||
|
let current_speed = time.relative_speed();
|
||||||
|
let new_speed = (current_speed * 0.5).max(1.0);
|
||||||
|
time.set_relative_speed(new_speed);
|
||||||
|
println!("Speed: {}x", new_speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset to normal speed with R
|
||||||
|
if keyboard_input.just_pressed(KeyCode::KeyR) {
|
||||||
|
time.set_relative_speed(1.0);
|
||||||
|
time.unpause();
|
||||||
|
println!("Speed reset to 1x");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_ui_scale(
|
||||||
|
windows: Query<&Window>,
|
||||||
|
mut ui_scale: ResMut<UiScale>,
|
||||||
|
egui_contexts: Query<&mut EguiContextSettings>,
|
||||||
|
) {
|
||||||
|
if let Ok(window) = windows.single() {
|
||||||
|
// Calculate scale factor based on physical resolution
|
||||||
|
// Use 1080p as base resolution (1920x1080)
|
||||||
|
let base_height = 1080.0;
|
||||||
|
let current_height = window.physical_height() as f32;
|
||||||
|
let new_scale_factor = current_height / base_height;
|
||||||
|
|
||||||
|
// Update scale factor if it changed significantly
|
||||||
|
if (new_scale_factor - ui_scale.scale_factor).abs() > 0.01 {
|
||||||
|
ui_scale.scale_factor = new_scale_factor;
|
||||||
|
ui_scale.current_font_size = ui_scale.base_font_size * new_scale_factor;
|
||||||
|
|
||||||
|
// Apply scaling to egui (affects WorldInspectorPlugin)
|
||||||
|
for mut egui_settings in egui_contexts {
|
||||||
|
egui_settings.scale_factor = new_scale_factor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_label_font_sizes(
|
||||||
|
mut label_query: Query<&mut TextFont, With<ObjectLabel>>,
|
||||||
|
ui_scale: Res<UiScale>,
|
||||||
|
) {
|
||||||
|
if ui_scale.is_changed() {
|
||||||
|
for mut text_font in label_query.iter_mut() {
|
||||||
|
text_font.font_size = ui_scale.current_font_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn initialize_camera_follow(
|
fn initialize_camera_follow(
|
||||||
earth_query: Query<Entity, (With<Earth>, With<Trackable>)>,
|
earth_query: Query<Entity, (With<Earth>, With<Trackable>)>,
|
||||||
mut camera_follow: ResMut<CameraFollow>,
|
mut camera_follow: ResMut<CameraFollow>,
|
||||||
@ -430,7 +543,7 @@ const STEPS: usize = 100;
|
|||||||
// Time step calculation:
|
// Time step calculation:
|
||||||
// FixedUpdate runs at 64fps, 1 game second = 7 days, 100 steps per FixedUpdate
|
// FixedUpdate runs at 64fps, 1 game second = 7 days, 100 steps per FixedUpdate
|
||||||
// DT = (7 days / 64 fps) / 100 steps = 7 / (64 * 100) = 0.00109375 days per step
|
// DT = (7 days / 64 fps) / 100 steps = 7 / (64 * 100) = 0.00109375 days per step
|
||||||
const DT: f64 = 7.0 / (64.0 * STEPS as f64); // Time step in days
|
const DT: f64 = 1.0 / (64.0 * STEPS as f64); // Time step in days
|
||||||
|
|
||||||
fn n_body(mut query: Query<(&Mass, &mut Position, &mut Velocity)>) {
|
fn n_body(mut query: Query<(&Mass, &mut Position, &mut Velocity)>) {
|
||||||
// Collect all bodies data (mass, position, velocity)
|
// Collect all bodies data (mass, position, velocity)
|
||||||
@ -489,8 +602,8 @@ fn main() {
|
|||||||
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||||
primary_window: Some(Window {
|
primary_window: Some(Window {
|
||||||
title: "Solar Sim".to_string(),
|
title: "Solar Sim".to_string(),
|
||||||
mode: WindowMode::BorderlessFullscreen(MonitorSelection::Primary),
|
// mode: WindowMode::BorderlessFullscreen(MonitorSelection::Primary),
|
||||||
resolution: WindowResolution::default().with_scale_factor_override(2.0),
|
resolution: WindowResolution::default().with_scale_factor_override(1.0),
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
..default()
|
..default()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user