// ▄████████▄ + ███ + ▄█████████ ███ + // ███▀ ▀███ + + ███ ███▀ + ███ + + // ███ + ███ ███ ███ █████████ ███ ███ ███ ███ // ███ +███ ███ ███ ███ ███▐██████ ███ ███ ███ // ███ + ███ ███+ ███ +███ ███ + ███ ███ + ███ // ███▄ ▄███ ███▄ ███ ███ + ███ + ███ ███▄ ███ // ▀████████▀ + ▀███████ ███▄ ███▄ ▀████ ▀███████ // + + + ███ // + ▀████████████████████████████████████████████████████▀ // // Various common functions and constants use crate::prelude::*; use bevy::prelude::*; pub use bevy::math::{DQuat, DVec3}; pub use std::f32::consts::PI as PI32; pub use std::f64::consts::PI; pub const GAME_NAME: &str = "OutFly"; pub const CONF_FILE: &str = "outfly.toml"; pub const FONT: &str = "fonts/Yupiter-Regular.ttf"; pub const EPSILON32: f32 = 1e-9; pub const EPSILON: f64 = 1e-9; pub const COLOR_BODY: &str = "#888888"; // For simple text pub const COLOR_DIM: &str = "#666666"; // For darker, less important text pub const COLOR_PRIMARY: &str = "#BE1251"; // The "branding" color pub const COLOR_SECONDARY: &str = "#CCCCCC"; // For accents pub const COLOR_SUCCESS: &str = "#F0D50C"; // For positive outcomes pub const COLOR_DANGER: &str = "#CCCCCC"; // For critical situations pub const COLOR_WARNING: &str = "#F0D50C"; // For warnings #[inline] pub fn bool2vis(boolean: bool) -> Visibility { if boolean { Visibility::Inherited } else { Visibility::Hidden } } #[inline] pub fn style_fullscreen() -> Style { Style { width: Val::Vw(100.0), height: Val::Vh(100.0), position_type: PositionType::Absolute, top: Val::Px(0.0), left: Val::Px(0.0), ..default() } } #[inline] pub fn style_centered() -> Style { Style { width: Val::Percent(100.0), height: Val::Percent(100.0), align_items: AlignItems::Center, justify_content: JustifyContent::SpaceAround, ..default() } } pub fn alive(settings: Res) -> bool { return settings.alive; } pub fn in_control(settings: Res) -> bool { return settings.in_control(); } pub fn game_running(settings: Res) -> bool { return settings.is_game_running(); } pub fn in_shadow( light_source_pos: DVec3, light_source_r: f64, shadow_caster_pos: DVec3, shadow_caster_r: f64, camera_pos: DVec3, ) -> bool { if light_source_r < shadow_caster_r { error!("common::in_shadow only works if light_source_r > shadow_caster_r"); return false; } let direction = (shadow_caster_pos - light_source_pos).normalize(); let shadow_caster_to_player = camera_pos - shadow_caster_pos; // Calculate the distance to the shadow caster if the player was projected // onto the line of the shadow, with positive numbers = in the shadow, // negative numbers = in between light source and shadow caster. let projection_length = shadow_caster_to_player.dot(direction); if projection_length < 0.0 { return false; } let projection = projection_length * direction; // Calculate the vector to the closest point along the shadow line let closest_vector = shadow_caster_to_player - projection; let distance_between_light_and_caster = (shadow_caster_pos - light_source_pos).length(); let max_distance = shadow_caster_r + ((shadow_caster_r - light_source_r) / distance_between_light_and_caster) * projection_length; return closest_vector.length() < max_distance; } pub fn look_at_quat(from: DVec3, to: DVec3, up: DVec3) -> DQuat { let direction = (to - from).normalize(); let direction_len = direction.length_squared(); if direction_len < 1e-4 || direction_len.is_nan() { return DQuat::IDENTITY; } let right = up.cross(direction).normalize(); let corrected_up = direction.cross(right); let mat3 = bevy::math::DMat3::from_cols(right, corrected_up, direction); DQuat::from_mat3(&mat3) }