krabmaga 0.6.1

A modern developing art for reliable and efficient Agent-based Model (ABM) simulation with the Rust language.
Documentation
use crate::engine::state::State;
use bevy::camera::ScalingMode;
use bevy::math::Vec2;
use bevy::prelude::{
    Camera2d, Commands, OrthographicProjection, Projection, Query, Res, ResMut, Transform, With,
};
use bevy::window::{PrimaryWindow, Window};

use crate::visualization::{
    asset_handle_factory::AssetHandleFactoryResource,
    simulation_descriptor::SimulationDescriptor,
    visualization_state::VisualizationState,
    wrappers::{ActiveSchedule, ActiveState},
};

/// The main startup system which bootstraps a simple orthographic camera, centers it to aim at the simulation,
/// then calls the user provided init callback.
pub fn init_system<I: VisualizationState<S> + 'static + bevy::prelude::Resource, S: State>(
    on_init: Res<I>,
    mut sprite_factory: AssetHandleFactoryResource,
    mut commands: Commands,
    state_resource: ResMut<ActiveState<S>>,
    schedule_resource: ResMut<ActiveSchedule>,
    window: Query<&Window, With<PrimaryWindow>>,
    mut sim: ResMut<SimulationDescriptor>,
) {
    if let Ok(window) = window.single() {
        // Right handed coordinate system, equal to how it is implemented in [`OrthographicProjection::new_2d()`].
        let far = 1000.;
        // Offset the whole simulation to the left to take the width of the UI panel into account.
        let ui_offset = -sim.ui_width;
        // Scale the simulation so it fills the portion of the screen not covered by the UI panel.
        let scale_x = sim.width / (window.width() + ui_offset);
        // The translation x must depend on the scale_x to keep the left offset constant between window resizes.
        let mut initial_transform = Transform::from_xyz(ui_offset * scale_x, 0., far - 0.1);
        initial_transform.scale.x = scale_x;
        initial_transform.scale.y = sim.height / window.height();

        commands.spawn((
            Camera2d,
            Projection::Orthographic(OrthographicProjection {
                far,
                scaling_mode: ScalingMode::WindowSize,
                viewport_origin: Vec2::new(0., 0.),
                ..OrthographicProjection::default_2d()
            }),
            initial_transform,
        ));

        on_init.on_init(
            &mut commands,
            &mut sprite_factory,
            &mut state_resource.0.lock().expect("error on lock"),
            &mut schedule_resource.0.lock().expect("error on lock"),
            &mut *sim,
        );
        on_init.setup_graphics(
            &mut schedule_resource.0.lock().expect("error on lock"),
            &mut commands,
            &mut state_resource.0.lock().expect("error on lock"),
            sprite_factory,
        )
    }
}