use std::error::Error; use std::path::Path; use engine::Engine; use engine::asset::Assets; use engine::camera::fly::{ Extension as FlyCameraExtension, Fly as FlyCamera, Options as FlyCameraOptions, }; use engine::camera::{Active as ActiveCamera, Camera}; use engine::color::Color; use engine::data_types::dimens::Dimens3; use engine::ecs::actions::Actions; use engine::ecs::event::component::Added; use engine::ecs::pair::Pair; use engine::ecs::phase::START as START_PHASE; use engine::ecs::sole::Single; use engine::ecs::system::observer::Observe; use engine::input::Extension as InputExtension; use engine::lighting::{AttenuationParams, GlobalLight, PointLight}; use engine::material::{Flags as MaterialFlags, Material}; use engine::mesh::cube::{ CreationSpec as CubeMeshCreationSpec, create as cube_mesh_create, }; use engine::model::{Materials as ModelMaterials, Model, Spec as ModelSpec}; use engine::renderer::GraphicsProperties; use engine::renderer::opengl::Extension as OpenglRendererExtension; use engine::transform::WorldPosition; use engine::vector::Vec3; use engine::windowing::window::{ CreationAttributes as WindowCreationAttributes, CursorGrabMode as WindowCursorGrabMode, Window, }; use tracing::level_filters::LevelFilter; use tracing_subscriber::EnvFilter; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; const YELLOW: Color = Color { red: 0.988235294118, green: 0.941176470588, blue: 0.0274509803922, }; const RESOURCE_DIR: &str = "res"; fn main() -> Result<(), Box> { tracing_subscriber::registry() .with(tracing_subscriber::fmt::layer()) .with( EnvFilter::builder() .with_default_directive(LevelFilter::DEBUG.into()) .from_env()?, ) .init(); let mut engine = Engine::new(); engine.spawn(( Camera::default(), WorldPosition { position: Vec3 { x: 0.0, y: 0.0, z: 3.0 }, }, ActiveCamera, FlyCamera::default(), )); engine.add_sole(GlobalLight::default())?; engine.register_system(*START_PHASE, init); engine.register_observer(configure_window_on_added); engine.add_extension(engine::windowing::Extension::default()); engine.add_extension(OpenglRendererExtension::default()); engine.add_extension(FlyCameraExtension(FlyCameraOptions { mouse_sensitivity: 0.2, })); engine.add_extension(InputExtension::default()); engine.spawn(( WindowCreationAttributes::default().with_title("Game"), GraphicsProperties::builder().debug(true).build(), )); engine.start(); Ok(()) } fn configure_window_on_added(observe: Observe>) { for evt_match in &observe { let mut window = evt_match.get_added_comp_mut(); window.cursor_visible = false; window.cursor_grab_mode = WindowCursorGrabMode::Locked; window.set_changed(); } } fn init(mut assets: Single, mut actions: Actions) { actions.spawn(( PointLight::builder() .diffuse(YELLOW) .attenuation_params(AttenuationParams { linear: 0.045, quadratic: 0.0075, ..Default::default() }) .build(), WorldPosition::from(Vec3 { x: -6.0, y: 3.0, z: 3.0 }), Model::new(assets.store_with_name_with("light_cube", |assets| { ModelSpec::builder() .mesh( assets.store_with_name( "light_cube_mesh", cube_mesh_create( CubeMeshCreationSpec::builder() .dimens(Dimens3::from(2.0)) .build(), |face_verts, _, _| face_verts, ), ), ) .materials(ModelMaterials::direct([( "surface", assets.store_with_name( "light_cube_surface_mat", Material::builder().ambient(YELLOW * 5.0).build(), ), )])) .material_name("surface") .build() })), MaterialFlags::builder().use_ambient_color(true).build(), )); actions.spawn(( Model::new(assets.load::(Path::new(RESOURCE_DIR).join("teapot.obj"))), WorldPosition::from(Vec3 { x: 1.6, y: 0.0, z: 0.0 }), )); }