Skip to content

Commit

Permalink
Upgrade to Bevy 0.15.0 (#664)
Browse files Browse the repository at this point in the history
* Upgrade to Bevy 0.15.0-dev.

Most of the work here was fallout from the gamepads-as-entities change
(bevyengine/bevy#12770), as well as the
`PartialReflect` changes.

This relies on bevyengine/bevy#15685. That PR
must be applied to Bevy for this to build.

The most recent upstream commit is
4bf647ff3b0ca7c8ca47496db9cfe03702328473.

* Switch to upstream AccumulatedFoo

* Try (unsuccessfully) to fix the failing tests

* Bumps bevy_egui requirement from 0.30 to 0.31

* Sets bevy requirement to 0.15.0

* Replaces deprecated SpriteBundle

* Applies system ordering suggestion

* Use AccumulatedMouseScroll and AccumulatedMouseMotion from bevy

* Fixes merge issues

* Runs formatter

* Gets button value from SpecificGamepadButton

* Ignores tests

* Fixes compilation issues

* Fixes docs

---------

Co-authored-by: Patrick Walton <[email protected]>
  • Loading branch information
mnmaita and pcwalton authored Dec 9, 2024
1 parent 212ff69 commit d40715f
Show file tree
Hide file tree
Showing 35 changed files with 1,031 additions and 1,011 deletions.
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ egui = ['dep:bevy_egui']

[dependencies]
leafwing_input_manager_macros = { path = "macros", version = "0.15.1" }
bevy = { version = "0.14.0-rc.3", default-features = false, features = [
bevy = { version = "0.15.0", default-features = false, features = [
"serialize",
] }
bevy_egui = { version = "0.30", optional = true }
bevy_egui = { version = "0.31", optional = true }

derive_more = { version = "0.99", default-features = false, features = [
"display",
Expand All @@ -62,14 +62,15 @@ dyn-eq = "0.1"
dyn-hash = "0.2"

[dev-dependencies]
bevy = { version = "0.14.0-rc.3", default-features = false, features = [
bevy = { version = "0.15.0", default-features = false, features = [
"bevy_asset",
"bevy_sprite",
"bevy_text",
"bevy_ui",
"bevy_render",
"bevy_core_pipeline",
"bevy_state",
"bevy_window",
"x11",
# TODO Remove these before release. See https://github.com/bevyengine/bevy/issues/13728
"ktx2",
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ and a single input can result in multiple actions being triggered, which can be
- Look up your current input state in a single `ActionState` component
- That pesky maximum of 16 system parameters got you down? Say goodbye to that input handling mega-system
- Ergonomic insertion API that seamlessly blends multiple input types for you
- Can't decide between `input_map.insert(Action::Jump, KeyCode::Space)` and `input_map.insert(Action::Jump, GamepadButtonType::South)`? Have both!
- Can't decide between `input_map.insert(Action::Jump, KeyCode::Space)` and `input_map.insert(Action::Jump, GamepadButton::South)`? Have both!
- Full support for arbitrary button combinations: chord your heart out.
- `input_map.insert(Action::Console, ButtonlikeChord::new([KeyCode::ControlLeft, KeyCode::Shift, KeyCode::KeyC]))`
- Sophisticated input disambiguation with the `ClashStrategy` enum: stop triggering individual buttons when you meant to press a chord!
Expand Down
4 changes: 2 additions & 2 deletions examples/axis_inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fn spawn_player(mut commands: Commands) {
// Let's bind the left stick for the move action
.with_dual_axis(Action::Move, GamepadStick::LEFT)
// And then bind the right gamepad trigger to the throttle action
.with(Action::Throttle, GamepadButtonType::RightTrigger2)
.with(Action::Throttle, GamepadButton::RightTrigger2)
// And we'll use the right stick's x-axis as a rudder control
.with_axis(
// Add an AxisDeadzone to process horizontal values of the right stick.
Expand All @@ -57,7 +57,7 @@ fn move_player(query: Query<&ActionState<Action>, With<Player>>) {

if action_state.pressed(&Action::Throttle) {
// Note that some gamepad buttons are also tied to axes, so even though we used a
// GamepadButtonType::RightTrigger2 binding to trigger the throttle action,
// GamepadButton::RightTrigger2 binding to trigger the throttle action,
// we can get a variable value here if you have a variable right trigger on your gamepad.
//
// If you don't have a variable trigger, this will just return 0.0 when not pressed and 1.0
Expand Down
4 changes: 2 additions & 2 deletions examples/default_controls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ impl PlayerAction {

// Default gamepad input bindings
input_map.insert_dual_axis(Self::Run, GamepadStick::LEFT);
input_map.insert(Self::Jump, GamepadButtonType::South);
input_map.insert(Self::UseItem, GamepadButtonType::RightTrigger2);
input_map.insert(Self::Jump, GamepadButton::South);
input_map.insert(Self::UseItem, GamepadButton::RightTrigger2);

// Default kbm input bindings
input_map.insert_dual_axis(Self::Run, VirtualDPad::wasd());
Expand Down
10 changes: 5 additions & 5 deletions examples/mouse_motion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ fn setup(mut commands: Commands) {
// via the `MouseMoveDirection` enum.
let input_map = InputMap::default().with_dual_axis(CameraMovement::Pan, MouseMove::default());
commands
.spawn(Camera2dBundle::default())
.spawn(Camera2d)
.insert(InputManagerBundle::with_map(input_map));

commands.spawn(SpriteBundle {
transform: Transform::from_scale(Vec3::new(100., 100., 1.)),
..default()
});
commands.spawn((
Sprite::default(),
Transform::from_scale(Vec3::new(100., 100., 1.)),
));
}

fn pan_camera(mut query: Query<(&mut Transform, &ActionState<CameraMovement>), With<Camera2d>>) {
Expand Down
10 changes: 5 additions & 5 deletions examples/mouse_wheel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ fn setup(mut commands: Commands) {
// Or even a digital dual-axis input!
.with_dual_axis(CameraMovement::Pan, MouseScroll::default().digital());
commands
.spawn(Camera2dBundle::default())
.spawn(Camera2d)
.insert(InputManagerBundle::with_map(input_map));

commands.spawn(SpriteBundle {
transform: Transform::from_scale(Vec3::new(100., 100., 1.)),
..default()
});
commands.spawn((
Sprite::default(),
Transform::from_scale(Vec3::new(100., 100., 1.)),
));
}

fn zoom_camera(
Expand Down
29 changes: 20 additions & 9 deletions examples/multiplayer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct PlayerBundle {
}

impl PlayerBundle {
fn input_map(player: Player) -> InputMap<Action> {
fn input_map(player: Player, gamepad_0: Entity, gamepad_1: Entity) -> InputMap<Action> {
let mut input_map = match player {
Player::One => InputMap::new([
(Action::Left, KeyCode::KeyA),
Expand All @@ -42,36 +42,47 @@ impl PlayerBundle {
// and gracefully handle disconnects
// Note that this step is not required:
// if it is skipped, all input maps will read from all connected gamepads
.with_gamepad(Gamepad { id: 0 }),
.with_gamepad(gamepad_0),
Player::Two => InputMap::new([
(Action::Left, KeyCode::ArrowLeft),
(Action::Right, KeyCode::ArrowRight),
(Action::Jump, KeyCode::ArrowUp),
])
.with_gamepad(Gamepad { id: 1 }),
.with_gamepad(gamepad_1),
};

// Each player will use the same gamepad controls, but on separate gamepads.
input_map.insert_multiple([
(Action::Left, GamepadButtonType::DPadLeft),
(Action::Right, GamepadButtonType::DPadRight),
(Action::Jump, GamepadButtonType::DPadUp),
(Action::Jump, GamepadButtonType::South),
(Action::Left, GamepadButton::DPadLeft),
(Action::Right, GamepadButton::DPadRight),
(Action::Jump, GamepadButton::DPadUp),
(Action::Jump, GamepadButton::South),
]);

input_map
}
}

fn spawn_players(mut commands: Commands) {
let gamepad_0 = commands.spawn(()).id();
let gamepad_1 = commands.spawn(()).id();

commands.spawn(PlayerBundle {
player: Player::One,
input_manager: InputManagerBundle::with_map(PlayerBundle::input_map(Player::One)),
input_manager: InputManagerBundle::with_map(PlayerBundle::input_map(
Player::One,
gamepad_0,
gamepad_1,
)),
});

commands.spawn(PlayerBundle {
player: Player::Two,
input_manager: InputManagerBundle::with_map(PlayerBundle::input_map(Player::Two)),
input_manager: InputManagerBundle::with_map(PlayerBundle::input_map(
Player::Two,
gamepad_0,
gamepad_1,
)),
});
}

Expand Down
37 changes: 21 additions & 16 deletions examples/register_gamepads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,45 +19,50 @@ enum Action {
}

// This is used to check if a player already exists and which entity to disconnect
//
// This maps gamepad entity to player.
#[derive(Resource, Default)]
struct JoinedPlayers(pub HashMap<Gamepad, Entity>);
struct JoinedPlayers(pub HashMap<Entity, Entity>);

#[derive(Component)]
struct Player {
// This gamepad is used to index each player
gamepad: Gamepad,
gamepad: Entity,
}

fn join(
mut commands: Commands,
mut joined_players: ResMut<JoinedPlayers>,
gamepads: Res<Gamepads>,
button_inputs: Res<ButtonInput<GamepadButton>>,
gamepads: Query<(Entity, &Gamepad)>,
) {
for gamepad in gamepads.iter() {
for (gamepad_entity, gamepad) in gamepads.iter() {
// Join the game when both bumpers (L+R) on the controller are pressed
// We drop down the Bevy's input to get the input from each gamepad
if button_inputs.pressed(GamepadButton::new(gamepad, GamepadButtonType::LeftTrigger))
&& button_inputs.pressed(GamepadButton::new(gamepad, GamepadButtonType::RightTrigger))
if gamepad.pressed(GamepadButton::LeftTrigger)
&& gamepad.pressed(GamepadButton::RightTrigger)
{
// Make sure a player cannot join twice
if !joined_players.0.contains_key(&gamepad) {
println!("Player {} has joined the game!", gamepad.id);
if !joined_players.0.contains_key(&gamepad_entity) {
println!("Player {} has joined the game!", gamepad_entity);

let input_map = InputMap::new([
(Action::Jump, GamepadButtonType::South),
(Action::Disconnect, GamepadButtonType::Select),
(Action::Jump, GamepadButton::South),
(Action::Disconnect, GamepadButton::Select),
])
// Make sure to set the gamepad or all gamepads will be used!
.with_gamepad(gamepad);
.with_gamepad(gamepad_entity);
let player = commands
.spawn(InputManagerBundle::with_map(input_map))
.insert(Player { gamepad })
.insert(Player {
gamepad: gamepad_entity,
})
.id();

// Insert the created player and its gamepad to the hashmap of joined players
// Since uniqueness was already checked above, we can insert here unchecked
joined_players.0.insert_unique_unchecked(gamepad, player);
joined_players
.0
.insert_unique_unchecked(gamepad_entity, player);
}
}
}
Expand All @@ -67,7 +72,7 @@ fn jump(action_query: Query<(&ActionState<Action>, &Player)>) {
// Iterate through each player to see if they jumped
for (action_state, player) in action_query.iter() {
if action_state.just_pressed(&Action::Jump) {
println!("Player {} jumped!", player.gamepad.id);
println!("Player {} jumped!", player.gamepad);
}
}
}
Expand All @@ -85,7 +90,7 @@ fn disconnect(
commands.entity(player_entity).despawn();
joined_players.0.remove(&player.gamepad);

println!("Player {} has disconnected!", player.gamepad.id);
println!("Player {} has disconnected!", player.gamepad);
}
}
}
8 changes: 4 additions & 4 deletions examples/send_actions_over_network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//! Note that [`ActionState`] can also be serialized and sent directly.
//! This approach will be less bandwidth efficient, but involve less complexity and CPU work.
use bevy::ecs::event::ManualEventReader;
use bevy::ecs::event::EventCursor;
use bevy::input::InputPlugin;
use bevy::prelude::*;
use leafwing_input_manager::action_diff::ActionDiffEvent;
Expand Down Expand Up @@ -137,13 +137,13 @@ fn spawn_player(mut commands: Commands) {
fn send_events<A: Send + Sync + 'static + Debug + Clone + Event>(
client_app: &App,
server_app: &mut App,
reader: Option<ManualEventReader<A>>,
) -> ManualEventReader<A> {
reader: Option<EventCursor<A>>,
) -> EventCursor<A> {
let client_events: &Events<A> = client_app.world().resource();
let mut server_events: Mut<Events<A>> = server_app.world_mut().resource_mut();

// Get an event reader, one way or another
let mut reader = reader.unwrap_or_else(|| client_events.get_reader());
let mut reader = reader.unwrap_or_else(|| client_events.get_cursor());

// Push the clients' events to the server
for client_event in reader.read(client_events) {
Expand Down
18 changes: 9 additions & 9 deletions examples/single_player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,34 +74,34 @@ impl PlayerBundle {

// Movement
input_map.insert(Up, KeyCode::ArrowUp);
input_map.insert(Up, GamepadButtonType::DPadUp);
input_map.insert(Up, GamepadButton::DPadUp);

input_map.insert(Down, KeyCode::ArrowDown);
input_map.insert(Down, GamepadButtonType::DPadDown);
input_map.insert(Down, GamepadButton::DPadDown);

input_map.insert(Left, KeyCode::ArrowLeft);
input_map.insert(Left, GamepadButtonType::DPadLeft);
input_map.insert(Left, GamepadButton::DPadLeft);

input_map.insert(Right, KeyCode::ArrowRight);
input_map.insert(Right, GamepadButtonType::DPadRight);
input_map.insert(Right, GamepadButton::DPadRight);

// Abilities
input_map.insert(Ability1, KeyCode::KeyQ);
input_map.insert(Ability1, GamepadButtonType::West);
input_map.insert(Ability1, GamepadButton::West);
input_map.insert(Ability1, MouseButton::Left);

input_map.insert(Ability2, KeyCode::KeyW);
input_map.insert(Ability2, GamepadButtonType::North);
input_map.insert(Ability2, GamepadButton::North);
input_map.insert(Ability2, MouseButton::Right);

input_map.insert(Ability3, KeyCode::KeyE);
input_map.insert(Ability3, GamepadButtonType::East);
input_map.insert(Ability3, GamepadButton::East);

input_map.insert(Ability4, KeyCode::Space);
input_map.insert(Ability4, GamepadButtonType::South);
input_map.insert(Ability4, GamepadButton::South);

input_map.insert(Ultimate, KeyCode::KeyR);
input_map.insert(Ultimate, GamepadButtonType::LeftTrigger2);
input_map.insert(Ultimate, GamepadButton::LeftTrigger2);

input_map
}
Expand Down
14 changes: 6 additions & 8 deletions examples/twin_stick_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl PlayerAction {
// Default gamepad input bindings
input_map.insert_dual_axis(Self::Move, GamepadStick::LEFT);
input_map.insert_dual_axis(Self::Look, GamepadStick::RIGHT);
input_map.insert(Self::Shoot, GamepadButtonType::RightTrigger);
input_map.insert(Self::Shoot, GamepadButton::RightTrigger);

// Default kbm input bindings
input_map.insert_dual_axis(Self::Move, VirtualDPad::wasd());
Expand Down Expand Up @@ -132,7 +132,7 @@ fn player_mouse_look(
let player_position = player_transform.translation;
if let Some(p) = window
.cursor_position()
.and_then(|cursor| camera.viewport_to_world(camera_transform, cursor))
.and_then(|cursor| camera.viewport_to_world(camera_transform, cursor).ok())
.and_then(|ray| {
Some(ray).zip(ray.intersect_plane(player_position, InfinitePlane3d::new(Vec3::Y)))
})
Expand Down Expand Up @@ -160,7 +160,7 @@ fn control_player(
if action_state.axis_pair(&PlayerAction::Move) != Vec2::ZERO {
// Note: In a real game we'd feed this into an actual player controller
// and respects the camera extrinsics to ensure the direction is correct
let move_delta = time.delta_seconds() * action_state.clamped_axis_pair(&PlayerAction::Move);
let move_delta = time.delta_secs() * action_state.clamped_axis_pair(&PlayerAction::Move);
player_transform.translation += Vec3::new(move_delta.x, 0.0, move_delta.y);
println!("Player moved to: {}", player_transform.translation.xz());
}
Expand All @@ -182,11 +182,9 @@ struct Player;

fn setup_scene(mut commands: Commands) {
// We need a camera
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(0.0, 10.0, 15.0)
.looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y),
..default()
});
commands
.spawn(Camera3d::default())
.insert(Transform::from_xyz(0.0, 10.0, 15.0).looking_at(Vec3::new(0.0, 0.0, 0.0), Vec3::Y));

// And a player
commands.spawn(Player).insert(Transform::default());
Expand Down
4 changes: 2 additions & 2 deletions examples/virtual_dpad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ fn spawn_player(mut commands: Commands) {
VirtualDPad::new(
KeyCode::KeyW,
KeyCode::KeyS,
GamepadButtonType::DPadLeft,
GamepadButtonType::DPadRight,
GamepadButton::DPadLeft,
GamepadButton::DPadRight,
),
);
commands
Expand Down
2 changes: 1 addition & 1 deletion macros/src/typetag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub(crate) fn expand_serde_typetag(input: &ItemImpl) -> syn::Result<TokenStream>
) {
#crate_path::typetag::Registry::register(
registry,
#ident,
(#ident).into(),
|de| Ok(::std::boxed::Box::new(
::bevy::reflect::erased_serde::deserialize::<#self_ty>(de)?,
)),
Expand Down
Loading

0 comments on commit d40715f

Please sign in to comment.