forked from jcornaz/heron
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: RotationContraints component (jcornaz#66)
- Loading branch information
Showing
8 changed files
with
269 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
use bevy::reflect::Reflect; | ||
|
||
/// Component that restrict what rotations can be caused by forces. | ||
/// | ||
/// Note that angular velocity may still be applied programmatically. This only restrict how rotation | ||
/// can change when force/torques are applied. | ||
/// | ||
/// # Example | ||
/// | ||
/// ``` | ||
/// # use bevy::prelude::*; | ||
/// # use heron_core::*; | ||
/// | ||
/// fn spawn(commands: &mut Commands) { | ||
/// commands.spawn(todo!("Spawn your sprite/mesh, incl. at least a GlobalTransform")) | ||
/// .with(Body::Sphere { radius: 1.0 }) | ||
/// .with(RotationConstraints::lock()); // Prevent rotation caused by forces | ||
/// } | ||
/// ``` | ||
#[derive(Debug, Copy, Clone, Reflect)] | ||
pub struct RotationConstraints { | ||
/// Set to true to prevent rotations around the x axis | ||
pub allow_x: bool, | ||
|
||
/// Set to true to prevent rotations around the y axis | ||
pub allow_y: bool, | ||
|
||
/// Set to true to prevent rotations around the Z axis | ||
pub allow_z: bool, | ||
} | ||
|
||
impl Default for RotationConstraints { | ||
fn default() -> Self { | ||
Self::allow() | ||
} | ||
} | ||
|
||
impl RotationConstraints { | ||
/// Lock rotations around all axes | ||
#[must_use] | ||
pub fn lock() -> Self { | ||
Self { | ||
allow_x: false, | ||
allow_y: false, | ||
allow_z: false, | ||
} | ||
} | ||
|
||
/// Allow rotations around all axes | ||
#[must_use] | ||
pub fn allow() -> Self { | ||
Self { | ||
allow_x: true, | ||
allow_y: true, | ||
allow_z: true, | ||
} | ||
} | ||
|
||
/// Allow rotation around the x axis only (and prevent rotating around the other axes) | ||
#[must_use] | ||
pub fn restrict_to_x_only() -> Self { | ||
Self { | ||
allow_x: true, | ||
allow_y: false, | ||
allow_z: false, | ||
} | ||
} | ||
|
||
/// Allow rotation around the y axis only (and prevent rotating around the other axes) | ||
#[must_use] | ||
pub fn restrict_to_y_only() -> Self { | ||
Self { | ||
allow_x: false, | ||
allow_y: true, | ||
allow_z: false, | ||
} | ||
} | ||
|
||
/// Allow rotation around the z axis only (and prevent rotating around the other axes) | ||
#[must_use] | ||
pub fn restrict_to_z_only() -> Self { | ||
Self { | ||
allow_x: false, | ||
allow_y: false, | ||
allow_z: true, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
#![allow(clippy::module_name_repetitions)] | ||
|
||
//! Extensions to bevy API | ||
use bevy::app::AppBuilder; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
#![cfg(feature = "2d")] | ||
|
||
use bevy::core::CorePlugin; | ||
use bevy::prelude::*; | ||
use bevy::reflect::TypeRegistryArc; | ||
|
||
use heron_core::{Body, RotationConstraints}; | ||
use heron_rapier::rapier::dynamics::{IntegrationParameters, RigidBodySet}; | ||
use heron_rapier::{BodyHandle, RapierPlugin}; | ||
|
||
fn test_app() -> App { | ||
let mut builder = App::build(); | ||
builder | ||
.init_resource::<TypeRegistryArc>() | ||
.add_plugin(CorePlugin) | ||
.add_plugin(RapierPlugin { | ||
step_per_second: None, | ||
parameters: IntegrationParameters::default(), | ||
}); | ||
builder.app | ||
} | ||
|
||
#[test] | ||
fn rotation_is_not_constrained_without_the_component() { | ||
let mut app = test_app(); | ||
|
||
let entity = app | ||
.world | ||
.spawn((GlobalTransform::default(), Body::Sphere { radius: 10.0 })); | ||
|
||
app.update(); | ||
|
||
let bodies = app.resources.get::<RigidBodySet>().unwrap(); | ||
|
||
assert!( | ||
bodies | ||
.get(app.world.get::<BodyHandle>(entity).unwrap().rigid_body()) | ||
.unwrap() | ||
.effective_world_inv_inertia_sqrt | ||
> 0.0 | ||
); | ||
} | ||
|
||
#[test] | ||
fn rotation_can_be_locked_at_creation() { | ||
let mut app = test_app(); | ||
|
||
let entity = app.world.spawn(( | ||
GlobalTransform::default(), | ||
Body::Sphere { radius: 10.0 }, | ||
RotationConstraints::lock(), | ||
)); | ||
|
||
app.update(); | ||
|
||
let bodies = app.resources.get::<RigidBodySet>().unwrap(); | ||
|
||
assert_eq!( | ||
bodies | ||
.get(app.world.get::<BodyHandle>(entity).unwrap().rigid_body()) | ||
.unwrap() | ||
.effective_world_inv_inertia_sqrt, | ||
0.0 | ||
); | ||
} | ||
|
||
#[test] | ||
fn rotation_can_be_locked_after_creation() { | ||
let mut app = test_app(); | ||
|
||
let entity = app | ||
.world | ||
.spawn((GlobalTransform::default(), Body::Sphere { radius: 10.0 })); | ||
|
||
app.update(); | ||
|
||
app.world | ||
.insert_one(entity, RotationConstraints::lock()) | ||
.unwrap(); | ||
|
||
app.update(); | ||
|
||
let bodies = app.resources.get::<RigidBodySet>().unwrap(); | ||
|
||
assert_eq!( | ||
bodies | ||
.get(app.world.get::<BodyHandle>(entity).unwrap().rigid_body()) | ||
.unwrap() | ||
.effective_world_inv_inertia_sqrt, | ||
0.0 | ||
); | ||
} | ||
|
||
#[test] | ||
fn rotation_is_unlocked_if_component_is_removed() { | ||
let mut app = test_app(); | ||
|
||
let entity = app.world.spawn(( | ||
GlobalTransform::default(), | ||
Body::Sphere { radius: 10.0 }, | ||
RotationConstraints::lock(), | ||
)); | ||
|
||
app.update(); | ||
|
||
app.world.remove_one::<RotationConstraints>(entity).unwrap(); | ||
|
||
app.update(); | ||
|
||
let bodies = app.resources.get::<RigidBodySet>().unwrap(); | ||
|
||
assert!( | ||
bodies | ||
.get(app.world.get::<BodyHandle>(entity).unwrap().rigid_body()) | ||
.unwrap() | ||
.effective_world_inv_inertia_sqrt | ||
> 0.0 | ||
); | ||
} |
Oops, something went wrong.