diff --git a/Cargo.lock b/Cargo.lock index 95596a7..831418f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -722,6 +722,18 @@ dependencies = [ "sysinfo", ] +[[package]] +name = "bevy_dolly" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e784bbab334c8025fdb175ad8a4f81d88ea82fa954714f2cf435565c806cbfc8" +dependencies = [ + "bevy", + "bevy_math", + "bevy_transform", + "leafwing-input-manager", +] + [[package]] name = "bevy_ecs" version = "0.14.2" @@ -2034,6 +2046,7 @@ version = "0.1.0" dependencies = [ "avian3d", "bevy", + "bevy_dolly", "bevy_editor_pls", "blenvy", "clap", @@ -3194,6 +3207,31 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leafwing-input-manager" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebb7f3227809906ca7ccc981aedf7805b5edb422b4265290cc749316c0faba4" +dependencies = [ + "bevy", + "derive_more", + "itertools", + "leafwing_input_manager_macros", + "serde", +] + +[[package]] +name = "leafwing_input_manager_macros" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d065e4f0771d9cc597e76d648da18476ad01fd50cd60ee585ee500f9cd8d696" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.85", +] + [[package]] name = "lewton" version = "0.10.2" diff --git a/Cargo.toml b/Cargo.toml index 7025d15..3490742 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] avian3d = "0.1.2" bevy = { version = "0.14.2", features = ["jpeg"] } +bevy_dolly = "0.0.4" bevy_editor_pls = "0.10.0" blenvy = "0.1.0-alpha.1" clap = { version = "4.5.20", features = ["derive"] } diff --git a/art/crooks.blend b/art/crooks.blend index bb63fc6..6f65c3a 100644 Binary files a/art/crooks.blend and b/art/crooks.blend differ diff --git a/assets/blueprints/Player.glb b/assets/blueprints/Player.glb index c835b8b..40bebd4 100644 Binary files a/assets/blueprints/Player.glb and b/assets/blueprints/Player.glb differ diff --git a/assets/levels/World.glb b/assets/levels/World.glb index 6c61f02..75f53fe 100644 Binary files a/assets/levels/World.glb and b/assets/levels/World.glb differ diff --git a/assets/levels/World.meta.ron b/assets/levels/World.meta.ron index 8ad824c..c20c279 100644 --- a/assets/levels/World.meta.ron +++ b/assets/levels/World.meta.ron @@ -2,9 +2,9 @@ assets: [ ("Player", File ( path: "blueprints/Player.glb" )), + ("body.001", File ( path: "materials/body.001.glb" )), ("head.001", File ( path: "materials/head.001.glb" )), ("glasses.001", File ( path: "materials/glasses.001.glb" )), - ("body.001", File ( path: "materials/body.001.glb" )), ("Hotel", File ( path: "blueprints/Hotel.glb" )), ("floor", File ( path: "materials/floor.glb" )), ] diff --git a/assets/registry.json b/assets/registry.json index 3cdda02..fc819f8 100644 --- a/assets/registry.json +++ b/assets/registry.json @@ -17206,6 +17206,17 @@ "type": "object", "typeInfo": "Struct" }, + "crooks::PlayerHead": { + "additionalProperties": false, + "isComponent": true, + "isResource": false, + "long_name": "crooks::PlayerHead", + "properties": {}, + "required": [], + "short_name": "PlayerHead", + "type": "object", + "typeInfo": "Struct" + }, "f32": { "isComponent": false, "isResource": false, diff --git a/src/main.rs b/src/main.rs index d16438a..6ba4089 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,11 @@ use avian3d::math::{Scalar, Vector}; -use avian3d::prelude::*; +use avian3d::prelude::{Collider, PhysicsDebugPlugin, PhysicsSet}; +use avian3d::PhysicsPlugins; use bevy::log::LogPlugin; use bevy::prelude::*; use bevy::state::app::StatesPlugin; +use bevy_dolly::prelude::{Arm, Position, Rig, Rotation, Smooth}; +use bevy_dolly::system::Dolly; use bevy_editor_pls::prelude::*; use blenvy::{BlenvyPlugin, BlueprintInfo, GameWorldTag, HideUntilReady, SpawnBlueprint}; use char_controller::{CharacterControllerBundle, CharacterControllerPlugin}; @@ -18,6 +21,14 @@ pub mod shared_net; #[reflect(Component)] pub struct Player; +#[derive(Component, PartialEq, Eq, Default, Reflect)] +#[reflect(Component)] +pub struct PlayerHead; + +#[derive(Component, PartialEq, Eq, Default, Reflect)] +#[reflect(Component)] +pub struct MainCamera; + lazy_static::lazy_static! { pub static ref CONFIG: Cli = { Cli::parse() @@ -51,7 +62,8 @@ pub struct Cli { fn main() { App::new() .register_type::() - // .insert_resource(Msaa::Sample4) + .register_type::() + .insert_resource(Msaa::Sample4) .insert_resource(AmbientLight { brightness: 200.0, ..default() @@ -67,10 +79,36 @@ fn main() { .add_plugins(BlenvyPlugin::default()) .add_systems(Startup, setup) .add_systems(Update, setup_player) + .add_systems( + Update, + (update_camera_rig, Dolly::::update_active), + ) + // .add_systems( + // PostUpdate, + // (update_camera_rig, Dolly::::update_active) + // .after(PhysicsSet::Sync) + // .before(TransformSystem::TransformPropagate), + // ) .run(); } fn setup(mut commands: Commands) { + commands.spawn(( + MainCamera, // The rig component tag + Rig::builder() // The rig itself + .with(Position::new(Vec3::ZERO)) // Start position + // Adds a driver for rotation + .with(Rotation::new(Quat::IDENTITY)) + // Interpolation when the translation is updated, also known as smoothing + .with(Smooth::new_position(0.3)) + // Interpolation when the rotation is updated (updated via the YawPitch driver) + .with(Smooth::new_rotation(0.3)) + // Moves the camera point out in the Z direction and uses the position as the pivot + // .with(Arm::new(Vec3::Z * 4.0)) + .build(), + Camera3dBundle::default(), // The camera which is related via the rig tag + )); + // commands.spawn(PointLightBundle { // transform: Transform::from_translation(Vec3::Y * 30.), // point_light: PointLight { @@ -127,3 +165,21 @@ fn setup_player( .with_movement(30.0, 0.92, 7.0, (30.0 as Scalar).to_radians()), ); } + +fn update_camera_rig( + q_player_head: Query<&GlobalTransform, (With, Without)>, + mut rig_q: Query<&mut Rig, Without>, +) { + let Ok(player_head_transform) = q_player_head.get_single() else { + return; + }; + let (_, rot, pos) = player_head_transform.to_scale_rotation_translation(); + + let mut rig = rig_q.single_mut(); + if let Some(d_rot) = rig.try_driver_mut::() { + d_rot.rotation = rot; + } + if let Some(d_pos) = rig.try_driver_mut::() { + d_pos.position = pos; + } +}