use lyra_engine::{math::{self, Vec3}, ecs::{World, components::{transform::TransformComponent, camera::CameraComponent, model::ModelComponent, DeltaTime}, EventQueue, SimpleSystem, Component, Criteria, CriteriaSchedule, BatchedSystem}, math::Transform, input::{KeyCode, InputButtons, MouseMotion, ActionHandler, Layout, Action, ActionKind, LayoutId, ActionMapping, Binding, ActionSource, ActionMappingId, InputActionPlugin, ActionState}, game::Game, plugin::Plugin, render::{window::{CursorGrabMode, WindowOptions}, light::{PointLight, directional::DirectionalLight, SpotLight}}, change_tracker::Ct}; use lyra_engine::assets::{ResourceManager, Model}; mod free_fly_camera; use free_fly_camera::{FreeFlyCameraPlugin, FreeFlyCamera}; use tracing::debug; struct FixedTimestep { max_tps: u32, fixed_time: f32, accumulator: f32, } impl FixedTimestep { pub fn new(max_tps: u32) -> Self { Self { max_tps, fixed_time: Self::calc_fixed_time(max_tps), accumulator: 0.0, } } fn calc_fixed_time(max_tps: u32) -> f32 { 1.0 / max_tps as f32 } fn set_tps(&mut self, tps: u32) { self.max_tps = tps; self.fixed_time = Self::calc_fixed_time(tps); } fn tps(&self) -> u32 { self.max_tps } fn fixed_time(&self) -> f32 { self.fixed_time } } impl Criteria for FixedTimestep { fn can_run(&mut self, world: &mut edict::World, check_count: u32) -> CriteriaSchedule { if check_count == 0 { let delta_time = world.get_resource::().unwrap(); self.accumulator += **delta_time; } if self.accumulator >= self.fixed_time { self.accumulator -= self.fixed_time; return CriteriaSchedule::YesAndLoop; } CriteriaSchedule::No } } #[derive(Clone)] struct TpsAccumulator(f32); #[derive(Component)] struct CubeFlag; #[async_std::main] async fn main() { let setup_sys = |world: &mut World| -> anyhow::Result<()> { { let mut window_options = world.get_resource_mut::>().unwrap(); window_options.cursor_grab = CursorGrabMode::Confined; window_options.cursor_visible = false; } let mut resman = world.get_resource_mut::().unwrap(); //let diffuse_texture = resman.request::("assets/happy-tree.png").unwrap(); let antique_camera_model = resman.request::("assets/AntiqueCamera.glb").unwrap(); //let cube_model = resman.request::("assets/cube-texture-bin.glb").unwrap(); let cube_model = resman.request::("assets/texture-sep/texture-sep.gltf").unwrap(); let crate_model = resman.request::("assets/crate/crate.gltf").unwrap(); drop(resman); world.spawn(( ModelComponent(antique_camera_model), TransformComponent::from(Transform::from_xyz(0.0, -5.0, -10.0)), )); { let mut cube_tran = Transform::from_xyz(-3.5, 0.0, -8.0); //cube_tran.rotate_y(math::Angle::Degrees(180.0)); world.spawn(( TransformComponent::from(cube_tran), ModelComponent(crate_model.clone()), CubeFlag, )); } { let mut light_tran = Transform::from_xyz(1.5, 2.5, 0.0); light_tran.scale = Vec3::new(0.5, 0.5, 0.5); light_tran.rotate_x(math::Angle::Degrees(-45.0)); light_tran.rotate_y(math::Angle::Degrees(25.0)); world.spawn(( DirectionalLight { color: Vec3::new(1.0, 1.0, 1.0), ambient: 0.3, diffuse: 1.0, specular: 1.3, }, TransformComponent::from(light_tran), ModelComponent(cube_model.clone()), )); } { let mut light_tran = Transform::from_xyz(-3.5, 0.2, -4.5); light_tran.scale = Vec3::new(0.5, 0.5, 0.5); world.spawn(( SpotLight { color: Vec3::new(1.0, 0.2, 0.2), cutoff: math::Angle::Degrees(12.5), outer_cutoff: math::Angle::Degrees(17.5), constant: 1.0, linear: 0.007, quadratic: 0.0002, ambient: 0.0, diffuse: 7.0, specular: 1.0, }, TransformComponent::from(light_tran), ModelComponent(cube_model.clone()), )); } /* { let mut light_tran = Transform::from_xyz(-5.0, 2.5, -9.5); light_tran.scale = Vec3::new(0.5, 0.5, 0.5); world.spawn(( PointLight { color: Vec3::new(1.0, 1.0, 1.0), intensity: 1.0, constant: 1.0, linear: 0.045, quadratic: 0.0075, ambient: 0.1, diffuse: 1.0, specular: 1.3, }, TransformComponent::from(light_tran), ModelComponent(cube_model.clone()), )); } */ { let mut light_tran = Transform::from_xyz(2.0, 2.5, -9.5); light_tran.scale = Vec3::new(0.5, 0.5, 0.5); world.spawn(( PointLight { color: Vec3::new(0.0, 0.0, 1.0), intensity: 3.3, constant: 1.0, linear: 0.09, quadratic: 0.032, ambient: 0.2, diffuse: 1.0, specular: 1.3, }, TransformComponent::from(light_tran), ModelComponent(cube_model), )); } let mut camera = CameraComponent::new_3d(); camera.transform.translation += math::Vec3::new(0.0, 0.0, 5.5); world.spawn(( camera, FreeFlyCamera::default() )); Ok(()) }; let fps_system = |world: &mut World| -> anyhow::Result<()> { let mut counter = world.get_resource_mut::().unwrap(); let fps = counter.tick(); println!("FPS: {fps}"); Ok(()) }; let fps_plugin = move |game: &mut Game| { let world = game.world(); world.insert_resource(fps_counter::FPSCounter::new()); }; let spin_system = |world: &mut World| -> anyhow::Result<()> { const SPEED: f32 = 4.0; let delta_time = **world.get_resource::().unwrap(); for (transform, _) in world.query_mut::<(&mut TransformComponent, &CubeFlag)>().iter_mut() { let t = &mut transform.transform; t.rotate_y(math::Angle::Degrees(SPEED * delta_time)); } /* for (transform, s) in world.query_mut::<(&mut TransformComponent, &mut SpotLight)>().iter_mut() { let t = &mut transform.transform; t.rotate_x(math::Angle::Degrees(SPEED * delta_time)); } */ Ok(()) }; let jiggle_plugin = move |game: &mut Game| { game.world().insert_resource(TpsAccumulator(0.0)); let mut sys = BatchedSystem::new(); sys.with_criteria(FixedTimestep::new(45)); //sys.with_system(spin_system); //sys.with_system(fps_system); game.with_system("fixed", sys, &[]); fps_plugin(game); }; let action_handler_plugin = |game: &mut Game| { let action_handler = ActionHandler::new() .add_layout(LayoutId::from(0)) .add_action("forward_backward", Action::new(ActionKind::Button)) .add_action("left_right", Action::new(ActionKind::Button)) .add_mapping(ActionMapping::new(LayoutId::from(0), ActionMappingId::from(0)) .bind("forward_backward", &[ ActionSource::Keyboard(KeyCode::W).into_binding_modifier(1.0), ActionSource::Keyboard(KeyCode::S).into_binding_modifier(-1.0) ]) .bind("left_right", &[ ActionSource::Keyboard(KeyCode::A).into_binding_modifier(1.0), ActionSource::Keyboard(KeyCode::D).into_binding_modifier(-1.0) ]) .finish() ); let test_system = |world: &mut World| -> anyhow::Result<()> { let handler = world.get_resource::().unwrap(); if let Some(alpha) = handler.get_pressed_modifier("forward_backward") { debug!("'forward_backward': {alpha}"); } if let Some(alpha) = handler.get_pressed_modifier("left_right") { debug!("'left_right': {alpha}"); } Ok(()) }; game.world().insert_resource(action_handler); game.with_plugin(InputActionPlugin); //game.with_system("test_actions", test_system, &[]); }; Game::initialize().await .with_plugin(lyra_engine::DefaultPlugins) .with_startup_system(setup_sys) .with_plugin(action_handler_plugin) //.with_plugin(fps_plugin) .with_plugin(jiggle_plugin) .with_plugin(FreeFlyCameraPlugin) .run().await; }