nightshade 0.56.0

A cross-platform data-oriented game engine.
Documentation
use crate::ecs::world::World;

#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn throttle_to_frame_rate_limit(world: &mut World) {
    use web_time::Instant;

    let Some(target_fps) = world
        .res::<crate::render::config::RenderSettings>()
        .frame_rate_limit
    else {
        return;
    };
    if !target_fps.is_finite() || target_fps <= 0.0 {
        return;
    }
    let Some(last_frame_start) = world
        .res::<crate::ecs::time::Time>()
        .last_frame_start_instant
    else {
        return;
    };

    let target_interval = std::time::Duration::from_secs_f32(1.0 / target_fps);
    let deadline = last_frame_start + target_interval;
    let busy_wait_floor = std::time::Duration::from_millis(1);

    let now = Instant::now();
    if now >= deadline {
        return;
    }
    let remaining = deadline - now;
    if remaining > busy_wait_floor {
        std::thread::sleep(remaining - busy_wait_floor);
    }
    while Instant::now() < deadline {
        std::hint::spin_loop();
    }
}

#[cfg(target_arch = "wasm32")]
pub(crate) fn throttle_to_frame_rate_limit(_world: &mut World) {}

#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn sync_macos_auto_frame_rate_limit(world: &mut World) {
    if !cfg!(target_os = "macos") {
        return;
    }
    let baseline = world
        .res::<crate::render::config::RendererState>()
        .auto_frame_rate_limit_baseline;
    if world
        .res::<crate::render::config::RenderSettings>()
        .vsync_enabled
    {
        if baseline.is_some() {
            if world
                .res::<crate::render::config::RenderSettings>()
                .frame_rate_limit
                == baseline
            {
                world
                    .res_mut::<crate::render::config::RenderSettings>()
                    .frame_rate_limit = None;
            }
            world
                .res_mut::<crate::render::config::RendererState>()
                .auto_frame_rate_limit_baseline = None;
        }
        return;
    }
    if baseline.is_some()
        || world
            .res::<crate::render::config::RenderSettings>()
            .frame_rate_limit
            .is_some()
    {
        return;
    }
    let Some(window_handle) = world
        .res::<crate::ecs::window::resources::Window>()
        .handle
        .clone()
    else {
        return;
    };
    let Some(target) = current_monitor_frame_rate_target(&window_handle) else {
        return;
    };
    world
        .res_mut::<crate::render::config::RenderSettings>()
        .frame_rate_limit = Some(target);
    world
        .res_mut::<crate::render::config::RendererState>()
        .auto_frame_rate_limit_baseline = Some(target);
}

#[cfg(target_arch = "wasm32")]
pub(crate) fn sync_macos_auto_frame_rate_limit(_world: &mut World) {}

#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn refresh_macos_frame_rate_limit(
    world: &mut World,
    window_handle: &std::sync::Arc<winit::window::Window>,
) {
    if !cfg!(target_os = "macos") {
        return;
    }
    if world
        .res::<crate::render::config::RenderSettings>()
        .vsync_enabled
    {
        return;
    }
    let baseline = world
        .res::<crate::render::config::RendererState>()
        .auto_frame_rate_limit_baseline;
    if baseline.is_none() {
        return;
    }
    if world
        .res::<crate::render::config::RenderSettings>()
        .frame_rate_limit
        != baseline
    {
        return;
    }
    let Some(target) = current_monitor_frame_rate_target(window_handle) else {
        return;
    };
    world
        .res_mut::<crate::render::config::RenderSettings>()
        .frame_rate_limit = Some(target);
    world
        .res_mut::<crate::render::config::RendererState>()
        .auto_frame_rate_limit_baseline = Some(target);
}

#[cfg(target_arch = "wasm32")]
pub(crate) fn refresh_macos_frame_rate_limit(
    _world: &mut World,
    _window_handle: &std::sync::Arc<winit::window::Window>,
) {
}

#[cfg(not(target_arch = "wasm32"))]
fn current_monitor_frame_rate_target(
    window_handle: &std::sync::Arc<winit::window::Window>,
) -> Option<f32> {
    let monitor = window_handle.current_monitor()?;
    let millihertz = monitor.refresh_rate_millihertz()?;
    let refresh_hz = millihertz as f32 / 1000.0;
    if refresh_hz > 1.0 {
        Some(refresh_hz - 1.0)
    } else {
        None
    }
}

#[cfg(target_arch = "wasm32")]
pub(crate) fn wasm_capped_dpr(css_width: f64, css_height: f64, raw_dpr: f64) -> f64 {
    let smallest_css = css_width.min(css_height);
    let max_dpr = if smallest_css < 700.0 { 1.5 } else { 2.0 };
    raw_dpr.clamp(1.0, max_dpr)
}