|
|
@ -57,6 +57,8 @@ use std::collections::HashMap;
|
|
|
|
use futures::FutureExt;
|
|
|
|
use futures::FutureExt;
|
|
|
|
use config::Config;
|
|
|
|
use config::Config;
|
|
|
|
use log::LevelFilter;
|
|
|
|
use log::LevelFilter;
|
|
|
|
|
|
|
|
use crate::runtime::state::RuntimeState;
|
|
|
|
|
|
|
|
use winit_24::event_loop::EventLoopProxy;
|
|
|
|
|
|
|
|
|
|
|
|
mod camera;
|
|
|
|
mod camera;
|
|
|
|
mod components;
|
|
|
|
mod components;
|
|
|
@ -108,12 +110,13 @@ fn main() {
|
|
|
|
|
|
|
|
|
|
|
|
let logger = env_logger::builder().filter(Some("minimal_viable_game_engine"), LevelFilter::Info).init();
|
|
|
|
let logger = env_logger::builder().filter(Some("minimal_viable_game_engine"), LevelFilter::Info).init();
|
|
|
|
|
|
|
|
|
|
|
|
let mut settings = Config::default();
|
|
|
|
|
|
|
|
settings
|
|
|
|
|
|
|
|
// File::with_name(..) is shorthand for File::from(Path::new(..))
|
|
|
|
|
|
|
|
.merge(File::with_name("conf/entity_spawns.toml")).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log::info!("{:#?}", settings);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// for i in settings.get("entities") {
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut world = World::default();
|
|
|
|
let mut world = World::default();
|
|
|
|
|
|
|
|
|
|
|
@ -121,6 +124,11 @@ fn main() {
|
|
|
|
.add_system(render::system::imgui_prepare_system())
|
|
|
|
.add_system(render::system::imgui_prepare_system())
|
|
|
|
.build();
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut load_schedule = Schedule::builder()
|
|
|
|
|
|
|
|
.add_system(runtime::system::runtime_load_system())
|
|
|
|
|
|
|
|
.add_system(runtime::system::runtime_spawn_system())
|
|
|
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
|
|
let mut render_schedule = Schedule::builder()
|
|
|
|
let mut render_schedule = Schedule::builder()
|
|
|
|
.add_system(render::system::render_test_system())
|
|
|
|
.add_system(render::system::render_test_system())
|
|
|
|
.build();
|
|
|
|
.build();
|
|
|
@ -176,7 +184,6 @@ fn main() {
|
|
|
|
|
|
|
|
|
|
|
|
// The renderer
|
|
|
|
// The renderer
|
|
|
|
let mut renderer = render::state::RenderState::init(&window, &mut imgui_context);
|
|
|
|
let mut renderer = render::state::RenderState::init(&window, &mut imgui_context);
|
|
|
|
preload_meshes("./resources");
|
|
|
|
|
|
|
|
entity_loading(&mut world, &mut renderer);
|
|
|
|
entity_loading(&mut world, &mut renderer);
|
|
|
|
|
|
|
|
|
|
|
|
resources.insert(renderer);
|
|
|
|
resources.insert(renderer);
|
|
|
@ -199,48 +206,12 @@ fn main() {
|
|
|
|
|
|
|
|
|
|
|
|
// And our event stack
|
|
|
|
// And our event stack
|
|
|
|
resources.insert(Vec::<OwnedEvent<OwnedEventExtension>>::new());
|
|
|
|
resources.insert(Vec::<OwnedEvent<OwnedEventExtension>>::new());
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let event_loop_proxy = event_loop.create_proxy();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::thread::spawn(move || {
|
|
|
|
|
|
|
|
let mut gilrs = Gilrs::new().unwrap();
|
|
|
|
|
|
|
|
// Iterate over all connected gamepads
|
|
|
|
|
|
|
|
let mut gamepad: Option<Gamepad> = None;
|
|
|
|
|
|
|
|
for (_id, gamepad_) in gilrs.gamepads() {
|
|
|
|
|
|
|
|
if gamepad_.name() == "PS4" {
|
|
|
|
|
|
|
|
gamepad = Some(gamepad_);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// println!(
|
|
|
|
|
|
|
|
// "{} is {:?} {:?}",
|
|
|
|
|
|
|
|
// gamepad_.name(),
|
|
|
|
|
|
|
|
// gamepad_.power_info(),
|
|
|
|
|
|
|
|
// gamepad_.id()
|
|
|
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut active_gamepad = None;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
loop {
|
|
|
|
// Our init and runtime data
|
|
|
|
while let Some(GilEvent { id, event, time }) = gilrs.next_event() {
|
|
|
|
resources.insert(RuntimeState::new())
|
|
|
|
//println!("{:?} New event from {}: {:?}", time, id, event);
|
|
|
|
};
|
|
|
|
active_gamepad = Some(id);
|
|
|
|
|
|
|
|
event_loop_proxy
|
|
|
|
|
|
|
|
.send_event(OwnedEventExtension::GamepadEvent {
|
|
|
|
|
|
|
|
gil_event: GilEvent { id, event, time },
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.ok();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // You can also use cached gamepad state
|
|
|
|
|
|
|
|
// if let Some(gamepad) = active_gamepad.map(|id| gilrs.gamepad(id)) {
|
|
|
|
|
|
|
|
// if gamepad.is_pressed(Button::South) {
|
|
|
|
|
|
|
|
// println!("Button South is pressed (XBox - A, PS - X)");
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
|
|
|
setup_gamepad(&event_loop);
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut elapsed_time: f32 = {
|
|
|
|
let mut elapsed_time: f32 = {
|
|
|
|
// deltatime since last frame
|
|
|
|
// deltatime since last frame
|
|
|
@ -256,7 +227,11 @@ fn main() {
|
|
|
|
event_loop.run(move |event, _, control_flow| {
|
|
|
|
event_loop.run(move |event, _, control_flow| {
|
|
|
|
*control_flow = ControlFlow::Poll;
|
|
|
|
*control_flow = ControlFlow::Poll;
|
|
|
|
match event {
|
|
|
|
match event {
|
|
|
|
event::Event::NewEvents(cause) => {}
|
|
|
|
event::Event::NewEvents(cause) => {
|
|
|
|
|
|
|
|
if cause == winit_24::event::StartCause::Init {
|
|
|
|
|
|
|
|
load_schedule.execute(&mut world, &mut resources);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This is the big boy section of the event loop
|
|
|
|
// This is the big boy section of the event loop
|
|
|
|
// We : dispatch events and clear the queue, query the loops
|
|
|
|
// We : dispatch events and clear the queue, query the loops
|
|
|
@ -341,76 +316,51 @@ fn main() {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn preload_meshes(resources_path: &str) -> HashMap<String, RawMesh> {
|
|
|
|
pub fn setup_gamepad(event_loop: &EventLoop<OwnedEventExtension>) {
|
|
|
|
|
|
|
|
|
|
|
|
log::info!("Preloading meshes...");
|
|
|
|
let event_loop_proxy = event_loop.create_proxy();
|
|
|
|
let mut output = HashMap::default();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let paths = fs::read_dir(resources_path).unwrap();
|
|
|
|
std::thread::spawn(move || {
|
|
|
|
for file in paths {
|
|
|
|
let mut gilrs = Gilrs::new().unwrap();
|
|
|
|
let filepath = file.unwrap().path().into_os_string();
|
|
|
|
// Iterate over all connected gamepads
|
|
|
|
let filepath = filepath.to_str().unwrap();
|
|
|
|
let mut gamepad: Option<Gamepad> = None;
|
|
|
|
if filepath.ends_with(".obj") {
|
|
|
|
for (_id, gamepad_) in gilrs.gamepads() {
|
|
|
|
let mesh = load_obj(filepath).unwrap();
|
|
|
|
if gamepad_.name() == "PS4" {
|
|
|
|
output.insert(filepath.to_string(), mesh);
|
|
|
|
gamepad = Some(gamepad_);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// println!(
|
|
|
|
|
|
|
|
// "{} is {:?} {:?}",
|
|
|
|
|
|
|
|
// gamepad_.name(),
|
|
|
|
|
|
|
|
// gamepad_.power_info(),
|
|
|
|
|
|
|
|
// gamepad_.id()
|
|
|
|
|
|
|
|
// );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut active_gamepad = None;
|
|
|
|
|
|
|
|
|
|
|
|
output
|
|
|
|
loop {
|
|
|
|
// I guess it's fine to have them loaded to the gpu
|
|
|
|
while let Some(GilEvent { id, event, time }) = gilrs.next_event() {
|
|
|
|
// But I also want to preserve the raw data
|
|
|
|
//println!("{:?} New event from {}: {:?}", time, id, event);
|
|
|
|
|
|
|
|
active_gamepad = Some(id);
|
|
|
|
|
|
|
|
event_loop_proxy
|
|
|
|
|
|
|
|
.send_event(OwnedEventExtension::GamepadEvent {
|
|
|
|
|
|
|
|
gil_event: GilEvent { id, event, time },
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.ok();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn load_colliding_mesh_entity(world: &mut World, renderer: &mut render::state::RenderState, mesh_path: &str) {
|
|
|
|
// // You can also use cached gamepad state
|
|
|
|
|
|
|
|
// if let Some(gamepad) = active_gamepad.map(|id| gilrs.gamepad(id)) {
|
|
|
|
|
|
|
|
// if gamepad.is_pressed(Button::South) {
|
|
|
|
|
|
|
|
// println!("Button South is pressed (XBox - A, PS - X)");
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
let mut static_floor_body = RigidBodyBuilder::new_static()
|
|
|
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
|
|
|
.position(Isometry3::new(Vector3::new(0.0, -8.0, 0.0), Vector::y()))
|
|
|
|
}
|
|
|
|
.build();
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//let pair = import_mesh("./resources/terrain.obj");
|
|
|
|
|
|
|
|
let raw_mesh = load_obj(mesh_path).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let floor_collider = ColliderBuilder::trimesh(
|
|
|
|
|
|
|
|
raw_mesh.vertices
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.map(|v| v.position())
|
|
|
|
|
|
|
|
.collect(),
|
|
|
|
|
|
|
|
raw_mesh.indices
|
|
|
|
|
|
|
|
).build();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let plane_mesh = renderer.load_mesh_to_buffer(
|
|
|
|
|
|
|
|
mesh_path,
|
|
|
|
|
|
|
|
Some(wgpu::Color {
|
|
|
|
|
|
|
|
r: 1.0,
|
|
|
|
|
|
|
|
g: 0.7,
|
|
|
|
|
|
|
|
b: 0.3,
|
|
|
|
|
|
|
|
a: 1.0,
|
|
|
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let plane_entity: Entity = world.push((
|
|
|
|
|
|
|
|
Position {
|
|
|
|
|
|
|
|
x: 0.0,
|
|
|
|
|
|
|
|
y: -8.0,
|
|
|
|
|
|
|
|
z: 0.0,
|
|
|
|
|
|
|
|
rot: Euler {
|
|
|
|
|
|
|
|
x: Deg(0.0),
|
|
|
|
|
|
|
|
y: Deg(0.0),
|
|
|
|
|
|
|
|
z: Deg(0.0),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
plane_mesh,
|
|
|
|
|
|
|
|
Physics {
|
|
|
|
|
|
|
|
rigid_body: static_floor_body,
|
|
|
|
|
|
|
|
rigid_body_handle: None,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
Collider {
|
|
|
|
|
|
|
|
collider: floor_collider,
|
|
|
|
|
|
|
|
collider_handle: None,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderState) {
|
|
|
|
pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderState) {
|
|
|
|
let monkey_mesh =
|
|
|
|
let monkey_mesh =
|
|
|
@ -420,7 +370,7 @@ pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderSta
|
|
|
|
let ball_mesh =
|
|
|
|
let ball_mesh =
|
|
|
|
renderer.load_mesh_to_buffer("./resources/ball.obj", Some(wgpu::Color::BLUE)).unwrap();
|
|
|
|
renderer.load_mesh_to_buffer("./resources/ball.obj", Some(wgpu::Color::BLUE)).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
load_colliding_mesh_entity(world, renderer, "./resources/test-textured.obj");
|
|
|
|
//load_colliding_mesh_entity(world, renderer, "./resources/test-textured.obj");
|
|
|
|
|
|
|
|
|
|
|
|
let camera_ent: Entity = world.push((
|
|
|
|
let camera_ent: Entity = world.push((
|
|
|
|
Camera {
|
|
|
|
Camera {
|
|
|
@ -435,8 +385,6 @@ pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderSta
|
|
|
|
CameraController::new(3.0, 1.0),
|
|
|
|
CameraController::new(3.0, 1.0),
|
|
|
|
));
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let light_entity: Entity = world.push((
|
|
|
|
let light_entity: Entity = world.push((
|
|
|
|
Position {
|
|
|
|
Position {
|
|
|
|
x: 0.0,
|
|
|
|
x: 0.0,
|
|
|
@ -462,71 +410,5 @@ pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderSta
|
|
|
|
renderer.create_light(),
|
|
|
|
renderer.create_light(),
|
|
|
|
));
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
let offset = cgmath::vec3(2.0, 2.0, 2.0);
|
|
|
|
|
|
|
|
let transform = Decomposed {
|
|
|
|
|
|
|
|
disp: offset.clone(),
|
|
|
|
|
|
|
|
rot: Quaternion::from_axis_angle(offset.normalize(), Deg(50.0)),
|
|
|
|
|
|
|
|
scale: 1.0,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let monkey_entity: Entity = world.push((
|
|
|
|
|
|
|
|
Position {
|
|
|
|
|
|
|
|
x: 1.0,
|
|
|
|
|
|
|
|
y: 5.0,
|
|
|
|
|
|
|
|
z: 2.0,
|
|
|
|
|
|
|
|
rot: Euler {
|
|
|
|
|
|
|
|
x: Deg(90.0),
|
|
|
|
|
|
|
|
y: Deg(45.0),
|
|
|
|
|
|
|
|
z: Deg(15.0),
|
|
|
|
|
|
|
|
}, //mx: cgmath::Matrix4::from(transform),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
monkey_mesh,
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut dynamic_ball_body = RigidBodyBuilder::new_dynamic()
|
|
|
|
|
|
|
|
.can_sleep(false)
|
|
|
|
|
|
|
|
.mass(1.0)
|
|
|
|
|
|
|
|
//.position(Isometry3::new(Vector3::new(0.0, 10.0, 0.0), Vector::y()))
|
|
|
|
|
|
|
|
.translation(0.0, 35.0, 0.0)
|
|
|
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let raw_mesh = load_obj("./resources/ball.obj").unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let ball_collider = ColliderBuilder::trimesh(
|
|
|
|
|
|
|
|
raw_mesh.vertices
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.map(|v| {
|
|
|
|
|
|
|
|
let position = v.position();
|
|
|
|
|
|
|
|
Point::<f32>::new(position.x, position.y, position.z)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.collect(),
|
|
|
|
|
|
|
|
raw_mesh.indices,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let ball_mesh: Entity = world.push((
|
|
|
|
|
|
|
|
Position {
|
|
|
|
|
|
|
|
x: 0.0,
|
|
|
|
|
|
|
|
y: 20.0,
|
|
|
|
|
|
|
|
z: 0.0,
|
|
|
|
|
|
|
|
rot: Euler {
|
|
|
|
|
|
|
|
x: Deg(25.0),
|
|
|
|
|
|
|
|
y: Deg(45.0),
|
|
|
|
|
|
|
|
z: Deg(15.0),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
ball_mesh,
|
|
|
|
|
|
|
|
Physics {
|
|
|
|
|
|
|
|
rigid_body: dynamic_ball_body,
|
|
|
|
|
|
|
|
rigid_body_handle: None,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
Collider {
|
|
|
|
|
|
|
|
collider: ball_collider,
|
|
|
|
|
|
|
|
collider_handle: None,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|