use raidillon_app::prelude::*; mod systems; use glam::{Quat, Vec3}; use rapier3d::dynamics::{CoefficientCombineRule, RigidBodyType}; use rapier3d::prelude::ColliderBuilder; use winit::event::{Event, WindowEvent}; use systems::debug_camera::FPSDebugCameraSystem; use crate::systems::common::should_draw_menu; use crate::systems::{ DisplaySettings, KeybindsSystem, KinematicCharacterController, MenuSystem, PhysicsSystem, PhysicsDebugSystem, }; const TEST_GLTF: &str = "checkered-sphere.glb"; const PLANE_GLTF: &str = "plane.glb"; const MAIN_SCENE_ID: &str = "main_scene"; #[derive(Default)] struct UpdateAspectRatioSystem; impl System for UpdateAspectRatioSystem { fn handle_event(&mut self, res: &mut EngineResources, scene: &mut Scene) { let pctx = res.get::().unwrap(); if let Event::WindowEvent { event: WindowEvent::Resized(sz), .. } = pctx.current_event { scene.world .query_mut::<&mut Camera>() .into_iter() .for_each(|(_, cam)| { cam.aspect = sz.width as f32 / sz.height as f32; }); } } } #[derive(Default)] struct MainSystem; impl System for MainSystem { fn load_world(&mut self, res: &mut EngineResources, scene: &mut Scene) { let pctx = res.get::().expect("PlatformContext missing").clone(); let physics = scene.resources.get_mut::().expect("Physics missing"); // Spawn Sphere { let tr = Transform { translation: Vec3::new(0.0, 5.0, 0.0), rotation: Quat::IDENTITY, scale: Vec3::new(1.0, 1.0, 1.0), }; let collider = ColliderBuilder::ball(1.0) .restitution(0.7) .restitution_combine_rule(CoefficientCombineRule::Max) .build(); let rb_handle = physics.add_rigid_body(RigidBodyType::Dynamic, tr, collider); pctx.asset_manager.borrow_mut().load_gltf(TEST_GLTF, &model_path(TEST_GLTF)); scene.world.spawn(( tr, ModelHandle(TEST_GLTF), RigidBodyComponent(rb_handle), )); } // Spawn Plane { let tr = Transform { translation: Vec3::new(0.0, 0.0, 0.0), rotation: Quat::IDENTITY, scale: Vec3::new(10.0, 1.0, 10.0), }; let collider = ColliderBuilder::cuboid(10.0, 0.01, 10.0).build(); let rb_handle = physics.add_rigid_body(RigidBodyType::Fixed, tr, collider); pctx.asset_manager.borrow_mut().load_gltf(PLANE_GLTF, &model_path(PLANE_GLTF)); scene.world.spawn(( tr, ModelHandle(PLANE_GLTF), RigidBodyComponent(rb_handle), )); } scene.world.spawn((Camera { eye: Vec3::new(0.0, 2.0, 3.0), center: Vec3::ZERO, up: Vec3::Y, fovy: 60_f32.to_radians(), aspect: pctx.frame_width / pctx.frame_height, znear: 0.1, zfar: 100.0}, CameraMode::default(), )); } fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { let ( pctx, input, ) = res.get_many_mut::<( PlatformContext, InputState, )>().unwrap(); let mut egui_queue = pctx.egui_queue.borrow_mut(); let time_ctx = pctx.time_ctx.clone(); let mut character_pos = Vec3::ZERO; for (_ent, (tr, ch_component)) in scene.world.query::<(&Transform, &CharacterBodyComponent)>().iter() { character_pos = tr.translation; } egui_queue.queue(move |egui_ctx| { // disable text selection on all labels. egui_ctx.style_mut(|style| { style.interaction.selectable_labels = false; }); egui::Window::new("Debug").show(egui_ctx, |ui| { ui.label("Hello World!"); ui.label(format!("Frame Delta: {:.3}", time_ctx.frame_dt)); ui.label(format!("Fixed Delta: {:.3}", time_ctx.fixed_dt)); ui.label(format!("FPS: {:.3}", 1.0 / time_ctx.frame_dt)); ui.label(format!("Character POS: {character_pos:.3}")); }); }); } } fn main() { raidillon_app::App::new() .add_system::() .add_system::() .add_system::() .add_system::() .add_system::() .add_system::() .add_system::() .add_system::() .add_system::() .add_scene(MAIN_SCENE_ID, Scene::new(MAIN_SCENE_ID.to_owned(), None)) .set_active_scene(MAIN_SCENE_ID) .run("Raidillon".to_string(), 2560, 1080); }