use std::ptr::NonNull; use lyra_engine::{math::{self, Vec3}, math::Transform, input::{KeyCode, ActionHandler, Action, ActionKind, LayoutId, ActionMapping, ActionSource, ActionMappingId, InputActionPlugin, MouseInput, MouseAxis, CommonActionLabel}, game::Game, render::{window::{CursorGrabMode, WindowOptions}, light::{PointLight, directional::DirectionalLight, SpotLight}}, change_tracker::Ct, ecs::{system::{Criteria, CriteriaSchedule, BatchedSystem, IntoSystem}, world::World, Component}, DeltaTime, scene::{TransformComponent, ModelComponent, CameraComponent}, lua::{LuaScriptingPlugin, LuaScript}, Script, ScriptList}; use lyra_engine::assets::{ResourceManager, Model}; mod free_fly_camera; use free_fly_camera::{FreeFlyCameraPlugin, FreeFlyCamera}; #[derive(Clone, Copy, Hash, Debug)] pub enum ActionLabel { MoveForwardBackward, MoveLeftRight, MoveUpDown, LookLeftRight, LookUpDown, LookRoll, } struct FixedTimestep { max_tps: u32, fixed_time: f32, accumulator: f32, } #[allow(dead_code)] 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, mut world: NonNull, check_count: u32) -> CriteriaSchedule { let world = unsafe { world.as_mut() }; if check_count == 0 { let delta_time = world.get_resource::(); 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::>(); window_options.cursor_grab = CursorGrabMode::Confined; window_options.cursor_visible = false; } let mut resman = world.get_resource_mut::(); //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 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(()) }; #[allow(unused_variables)] let fps_system = |world: &mut World| -> anyhow::Result<()> { let mut counter = world.get_resource_mut::(); let fps = counter.tick(); println!("FPS: {fps}"); Ok(()) }; let fps_plugin = move |game: &mut Game| { let world = game.world(); world.add_resource(fps_counter::FPSCounter::new()); }; let spin_system = |world: &mut World| -> anyhow::Result<()> { const SPEED: f32 = 4.0; let delta_time = **world.get_resource::(); for (mut transform, _) in world.view_iter::<(&mut TransformComponent, &CubeFlag)>() { let t = &mut transform.transform; t.rotate_y(math::Angle::Degrees(SPEED * delta_time)); } for (mut transform, _s) in world.view_iter::<(&mut TransformComponent, &mut SpotLight)>() { let t = &mut transform.transform; t.rotate_x(math::Angle::Degrees(SPEED * delta_time)); } Ok(()) }; let jiggle_plugin = move |game: &mut Game| { game.world().add_resource(TpsAccumulator(0.0)); let mut sys = BatchedSystem::new(); sys.with_criteria(FixedTimestep::new(45)); sys.with_system(spin_system.into_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(CommonActionLabel::MoveForwardBackward, Action::new(ActionKind::Axis)) .add_action(CommonActionLabel::MoveLeftRight, Action::new(ActionKind::Axis)) .add_action(CommonActionLabel::MoveUpDown, Action::new(ActionKind::Axis)) .add_action(CommonActionLabel::LookLeftRight, Action::new(ActionKind::Axis)) .add_action(CommonActionLabel::LookUpDown, Action::new(ActionKind::Axis)) .add_action(CommonActionLabel::LookRoll, Action::new(ActionKind::Axis)) .add_mapping(ActionMapping::new(LayoutId::from(0), ActionMappingId::from(0)) .bind(CommonActionLabel::MoveForwardBackward, &[ ActionSource::Keyboard(KeyCode::W).into_binding_modifier(1.0), ActionSource::Keyboard(KeyCode::S).into_binding_modifier(-1.0) ]) .bind(CommonActionLabel::MoveLeftRight, &[ ActionSource::Keyboard(KeyCode::A).into_binding_modifier(-1.0), ActionSource::Keyboard(KeyCode::D).into_binding_modifier(1.0) ]) .bind(CommonActionLabel::MoveUpDown, &[ ActionSource::Keyboard(KeyCode::C).into_binding_modifier(1.0), ActionSource::Keyboard(KeyCode::Z).into_binding_modifier(-1.0) ]) .bind(CommonActionLabel::LookLeftRight, &[ ActionSource::Mouse(MouseInput::Axis(MouseAxis::X)).into_binding(), ActionSource::Keyboard(KeyCode::Left).into_binding_modifier(-1.0), ActionSource::Keyboard(KeyCode::Right).into_binding_modifier(1.0), //ActionSource::Gamepad(GamepadFormat::DualAxis, GamepadInput::Axis(GamepadAxis::RThumbstickX)).into_binding(), ]) .bind(CommonActionLabel::LookUpDown, &[ ActionSource::Mouse(MouseInput::Axis(MouseAxis::Y)).into_binding(), ActionSource::Keyboard(KeyCode::Up).into_binding_modifier(-1.0), ActionSource::Keyboard(KeyCode::Down).into_binding_modifier(1.0), //ActionSource::Gamepad(GamepadFormat::DualAxis, GamepadInput::Axis(GamepadAxis::RThumbstickY)).into_binding(), ]) .bind(CommonActionLabel::LookRoll, &[ ActionSource::Keyboard(KeyCode::E).into_binding_modifier(-1.0), ActionSource::Keyboard(KeyCode::Q).into_binding_modifier(1.0), ]) .finish() ); /* #[allow(unused_variables)] let test_system = |world: &mut World| -> anyhow::Result<()> { let handler = world.get_resource::(); if let Some(alpha) = handler.get_axis_modifier("look_rotate") { debug!("'look_rotate': {alpha}"); } Ok(()) }; */ game.world().add_resource(action_handler); game.with_plugin(InputActionPlugin); //game.with_system("input_test", test_system, &[]); }; let script_test_plugin = |game: &mut Game| { game.with_plugin(LuaScriptingPlugin); let world = game.world(); let mut res_man = world.get_resource_mut::(); let script = res_man.request::("scripts/test.lua").unwrap(); drop(res_man); let script = Script::new("test.lua", script); let scripts = ScriptList::new(vec![script]); world.spawn((scripts,)); }; Game::initialize().await .with_plugin(lyra_engine::DefaultPlugins) .with_startup_system(setup_sys.into_system()) .with_plugin(action_handler_plugin) .with_plugin(script_test_plugin) //.with_plugin(fps_plugin) .with_plugin(jiggle_plugin) .with_plugin(FreeFlyCameraPlugin) .run().await; }