feat: update testbeds to bevy 0.13

This commit is contained in:
Sébastien Crozet
2024-03-24 17:25:42 +01:00
committed by Sébastien Crozet
parent f351dad938
commit 2df7258570
12 changed files with 222 additions and 194 deletions

View File

@@ -1,12 +1,12 @@
[package] [package]
name = "rapier_testbed2d-f64" name = "rapier_testbed2d-f64"
version = "0.18.0" version = "0.18.0"
authors = [ "Sébastien Crozet <developer@crozet.re>" ] authors = ["Sébastien Crozet <developer@crozet.re>"]
description = "Testbed for the Rapier 2-dimensional physics engine in Rust." description = "Testbed for the Rapier 2-dimensional physics engine in Rust."
homepage = "http://rapier.org" homepage = "http://rapier.org"
repository = "https://github.com/dimforge/rapier" repository = "https://github.com/dimforge/rapier"
categories = [ "science", "game-development", "mathematics", "simulation", "wasm"] categories = ["science", "game-development", "mathematics", "simulation", "wasm"]
keywords = [ "physics", "dynamics", "rigid", "real-time", "impulse_joints" ] keywords = ["physics", "dynamics", "rigid", "real-time", "impulse_joints"]
license = "Apache-2.0" license = "Apache-2.0"
edition = "2021" edition = "2021"
@@ -16,48 +16,48 @@ maintenance = { status = "actively-developed" }
[lib] [lib]
name = "rapier_testbed2d" name = "rapier_testbed2d"
path = "../../src_testbed/lib.rs" path = "../../src_testbed/lib.rs"
required-features = [ "dim2" ] required-features = ["dim2"]
[features] [features]
default = [ "dim2" ] default = ["dim2"]
dim2 = [ ] dim2 = []
parallel = [ "rapier/parallel", "num_cpus" ] parallel = ["rapier/parallel", "num_cpus"]
other-backends = [ "wrapped2d" ] other-backends = ["wrapped2d"]
[package.metadata.docs.rs] [package.metadata.docs.rs]
features = ["parallel", "other-backends"] features = ["parallel", "other-backends"]
[dependencies] [dependencies]
nalgebra = { version = "0.32", features = [ "rand" ] } nalgebra = { version = "0.32", features = ["rand"] }
rand = "0.8" rand = "0.8"
rand_pcg = "0.3" rand_pcg = "0.3"
instant = { version = "0.1", features = [ "web-sys", "now" ]} instant = { version = "0.1", features = ["web-sys", "now"] }
bitflags = "1" bitflags = "1"
num_cpus = { version = "1", optional = true } num_cpus = { version = "1", optional = true }
wrapped2d = { version = "0.4", optional = true } wrapped2d = { version = "0.4", optional = true }
crossbeam = "0.8" crossbeam = "0.8"
bincode = "1" bincode = "1"
Inflector = "0.11" Inflector = "0.11"
md5 = "0.7" md5 = "0.7"
bevy_egui = "0.23" bevy_egui = "0.26"
bevy_ecs = "0.12" bevy_ecs = "0.13"
bevy_core_pipeline = "0.12" bevy_core_pipeline = "0.13"
bevy_pbr = "0.12" bevy_pbr = "0.13"
bevy_sprite = "0.12" bevy_sprite = "0.13"
#bevy_prototype_debug_lines = "0.7" #bevy_prototype_debug_lines = "0.7"
# Dependencies for native only. # Dependencies for native only.
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
bevy = {version = "0.12", default-features = false, features = ["bevy_asset", "bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} bevy = { version = "0.13", default-features = false, features = ["bevy_asset", "bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"] }
# Dependencies for WASM only. # Dependencies for WASM only.
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
bevy = {version = "0.12", default-features = false, features = ["bevy_asset", "bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} bevy = { version = "0.13", default-features = false, features = ["bevy_asset", "bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"] }
#bevy_webgl2 = "0.5" #bevy_webgl2 = "0.5"
[dependencies.rapier] [dependencies.rapier]
package = "rapier2d-f64" package = "rapier2d-f64"
path = "../rapier2d-f64" path = "../rapier2d-f64"
version = "0.18.0" version = "0.18.0"
features = [ "serde-serialize", "debug-render", "profiler" ] features = ["serde-serialize", "debug-render", "profiler"]

View File

@@ -1,12 +1,12 @@
[package] [package]
name = "rapier_testbed2d" name = "rapier_testbed2d"
version = "0.18.0" version = "0.18.0"
authors = [ "Sébastien Crozet <developer@crozet.re>" ] authors = ["Sébastien Crozet <developer@crozet.re>"]
description = "Testbed for the Rapier 2-dimensional physics engine in Rust." description = "Testbed for the Rapier 2-dimensional physics engine in Rust."
homepage = "http://rapier.org" homepage = "http://rapier.org"
repository = "https://github.com/dimforge/rapier" repository = "https://github.com/dimforge/rapier"
categories = [ "science", "game-development", "mathematics", "simulation", "wasm"] categories = ["science", "game-development", "mathematics", "simulation", "wasm"]
keywords = [ "physics", "dynamics", "rigid", "real-time", "impulse_joints" ] keywords = ["physics", "dynamics", "rigid", "real-time", "impulse_joints"]
license = "Apache-2.0" license = "Apache-2.0"
edition = "2021" edition = "2021"
@@ -16,48 +16,48 @@ maintenance = { status = "actively-developed" }
[lib] [lib]
name = "rapier_testbed2d" name = "rapier_testbed2d"
path = "../../src_testbed/lib.rs" path = "../../src_testbed/lib.rs"
required-features = [ "dim2" ] required-features = ["dim2"]
[features] [features]
default = [ "dim2" ] default = ["dim2"]
dim2 = [ ] dim2 = []
parallel = [ "rapier/parallel", "num_cpus" ] parallel = ["rapier/parallel", "num_cpus"]
other-backends = [ "wrapped2d" ] other-backends = ["wrapped2d"]
[package.metadata.docs.rs] [package.metadata.docs.rs]
features = ["parallel", "other-backends"] features = ["parallel", "other-backends"]
[dependencies] [dependencies]
nalgebra = { version = "0.32", features = [ "rand" ] } nalgebra = { version = "0.32", features = ["rand"] }
rand = "0.8" rand = "0.8"
rand_pcg = "0.3" rand_pcg = "0.3"
instant = { version = "0.1", features = [ "web-sys", "now" ]} instant = { version = "0.1", features = ["web-sys", "now"] }
bitflags = "1" bitflags = "1"
num_cpus = { version = "1", optional = true } num_cpus = { version = "1", optional = true }
wrapped2d = { version = "0.4", optional = true } wrapped2d = { version = "0.4", optional = true }
crossbeam = "0.8" crossbeam = "0.8"
bincode = "1" bincode = "1"
Inflector = "0.11" Inflector = "0.11"
md5 = "0.7" md5 = "0.7"
bevy_egui = "0.23" bevy_egui = "0.26"
bevy_ecs = "0.12" bevy_ecs = "0.13"
bevy_core_pipeline = "0.12" bevy_core_pipeline = "0.13"
bevy_pbr = "0.12" bevy_pbr = "0.13"
bevy_sprite = "0.12" bevy_sprite = "0.13"
#bevy_prototype_debug_lines = "0.7" #bevy_prototype_debug_lines = "0.7"
# Dependencies for native only. # Dependencies for native only.
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
bevy = {version = "0.12", default-features = false, features = ["bevy_sprite", "bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} bevy = { version = "0.13", default-features = false, features = ["bevy_sprite", "bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"] }
# Dependencies for WASM only. # Dependencies for WASM only.
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
bevy = {version = "0.12", default-features = false, features = ["bevy_sprite", "bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} bevy = { version = "0.13", default-features = false, features = ["bevy_sprite", "bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"] }
#bevy_webgl2 = "0.5" #bevy_webgl2 = "0.5"
[dependencies.rapier] [dependencies.rapier]
package = "rapier2d" package = "rapier2d"
path = "../rapier2d" path = "../rapier2d"
version = "0.18.0" version = "0.18.0"
features = [ "serde-serialize", "debug-render", "profiler" ] features = ["serde-serialize", "debug-render", "profiler"]

View File

@@ -1,12 +1,12 @@
[package] [package]
name = "rapier_testbed3d-f64" name = "rapier_testbed3d-f64"
version = "0.18.0" version = "0.18.0"
authors = [ "Sébastien Crozet <developer@crozet.re>" ] authors = ["Sébastien Crozet <developer@crozet.re>"]
description = "Testbed for the Rapier 3-dimensional physics engine in Rust." description = "Testbed for the Rapier 3-dimensional physics engine in Rust."
homepage = "http://rapier.org" homepage = "http://rapier.org"
repository = "https://github.com/dimforge/rapier" repository = "https://github.com/dimforge/rapier"
categories = [ "science", "game-development", "mathematics", "simulation", "wasm"] categories = ["science", "game-development", "mathematics", "simulation", "wasm"]
keywords = [ "physics", "dynamics", "rigid", "real-time", "impulse_joints" ] keywords = ["physics", "dynamics", "rigid", "real-time", "impulse_joints"]
license = "Apache-2.0" license = "Apache-2.0"
edition = "2021" edition = "2021"
@@ -16,47 +16,47 @@ maintenance = { status = "actively-developed" }
[lib] [lib]
name = "rapier_testbed3d" name = "rapier_testbed3d"
path = "../../src_testbed/lib.rs" path = "../../src_testbed/lib.rs"
required-features = [ "dim3" ] required-features = ["dim3"]
[features] [features]
default = [ "dim3" ] default = ["dim3"]
dim3 = [ ] dim3 = []
parallel = [ "rapier/parallel", "num_cpus" ] parallel = ["rapier/parallel", "num_cpus"]
[package.metadata.docs.rs] [package.metadata.docs.rs]
features = ["parallel"] features = ["parallel"]
[dependencies] [dependencies]
nalgebra = { version = "0.32", features = [ "rand" ] } nalgebra = { version = "0.32", features = ["rand"] }
rand = "0.8" rand = "0.8"
rand_pcg = "0.3" rand_pcg = "0.3"
instant = { version = "0.1", features = [ "web-sys", "now" ]} instant = { version = "0.1", features = ["web-sys", "now"] }
bitflags = "1" bitflags = "1"
num_cpus = { version = "1", optional = true } num_cpus = { version = "1", optional = true }
crossbeam = "0.8" crossbeam = "0.8"
bincode = "1" bincode = "1"
md5 = "0.7" md5 = "0.7"
Inflector = "0.11" Inflector = "0.11"
serde = { version = "1", features = [ "derive" ] } serde = { version = "1", features = ["derive"] }
bevy_egui = "0.23" bevy_egui = "0.26"
bevy_ecs = "0.12" bevy_ecs = "0.13"
bevy_core_pipeline = "0.12" bevy_core_pipeline = "0.13"
bevy_pbr = "0.12" bevy_pbr = "0.13"
bevy_sprite = "0.12" bevy_sprite = "0.13"
#bevy_prototype_debug_lines = { version = "0.7", features = [ "3d" ] } #bevy_prototype_debug_lines = { version = "0.7", features = [ "3d" ] }
# Dependencies for native only. # Dependencies for native only.
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
bevy = {version = "0.12", default-features = false, features = ["bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} bevy = { version = "0.13", default-features = false, features = ["bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"] }
# Dependencies for WASM only. # Dependencies for WASM only.
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
bevy = {version = "0.12", default-features = false, features = ["bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} bevy = { version = "0.13", default-features = false, features = ["bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"] }
#bevy_webgl2 = "0.5" #bevy_webgl2 = "0.5"
[dependencies.rapier] [dependencies.rapier]
package = "rapier3d-f64" package = "rapier3d-f64"
path = "../rapier3d-f64" path = "../rapier3d-f64"
version = "0.18.0" version = "0.18.0"
features = [ "serde-serialize", "debug-render", "profiler" ] features = ["serde-serialize", "debug-render", "profiler"]

View File

@@ -1,12 +1,12 @@
[package] [package]
name = "rapier_testbed3d" name = "rapier_testbed3d"
version = "0.18.0" version = "0.18.0"
authors = [ "Sébastien Crozet <developer@crozet.re>" ] authors = ["Sébastien Crozet <developer@crozet.re>"]
description = "Testbed for the Rapier 3-dimensional physics engine in Rust." description = "Testbed for the Rapier 3-dimensional physics engine in Rust."
homepage = "http://rapier.org" homepage = "http://rapier.org"
repository = "https://github.com/dimforge/rapier" repository = "https://github.com/dimforge/rapier"
categories = [ "science", "game-development", "mathematics", "simulation", "wasm"] categories = ["science", "game-development", "mathematics", "simulation", "wasm"]
keywords = [ "physics", "dynamics", "rigid", "real-time", "impulse_joints" ] keywords = ["physics", "dynamics", "rigid", "real-time", "impulse_joints"]
license = "Apache-2.0" license = "Apache-2.0"
edition = "2021" edition = "2021"
@@ -16,51 +16,51 @@ maintenance = { status = "actively-developed" }
[lib] [lib]
name = "rapier_testbed3d" name = "rapier_testbed3d"
path = "../../src_testbed/lib.rs" path = "../../src_testbed/lib.rs"
required-features = [ "dim3" ] required-features = ["dim3"]
[features] [features]
default = [ "dim3" ] default = ["dim3"]
dim3 = [ ] dim3 = []
parallel = [ "rapier/parallel", "num_cpus" ] parallel = ["rapier/parallel", "num_cpus"]
other-backends = [ "physx", "physx-sys", "glam" ] other-backends = ["physx", "physx-sys", "glam"]
[package.metadata.docs.rs] [package.metadata.docs.rs]
features = ["parallel", "other-backends"] features = ["parallel", "other-backends"]
[dependencies] [dependencies]
nalgebra = { version = "0.32", features = [ "rand" ] } nalgebra = { version = "0.32", features = ["rand"] }
rand = "0.8" rand = "0.8"
rand_pcg = "0.3" rand_pcg = "0.3"
instant = { version = "0.1", features = [ "web-sys", "now" ]} instant = { version = "0.1", features = ["web-sys", "now"] }
bitflags = "1" bitflags = "1"
glam = { version = "0.24", optional = true } # For Physx glam = { version = "0.24", optional = true } # For Physx
num_cpus = { version = "1", optional = true } num_cpus = { version = "1", optional = true }
physx = { version = "0.19", features = [ "glam" ], optional = true } physx = { version = "0.19", features = ["glam"], optional = true }
physx-sys = { version = "0.11", optional = true } physx-sys = { version = "0.11", optional = true }
crossbeam = "0.8" crossbeam = "0.8"
bincode = "1" bincode = "1"
md5 = "0.7" md5 = "0.7"
Inflector = "0.11" Inflector = "0.11"
serde = { version = "1", features = [ "derive" ] } serde = { version = "1", features = ["derive"] }
bevy_egui = "0.23" bevy_egui = "0.26"
bevy_ecs = "0.12" bevy_ecs = "0.13"
bevy_core_pipeline = "0.12" bevy_core_pipeline = "0.13"
bevy_pbr = "0.12" bevy_pbr = "0.13"
bevy_sprite = "0.12" bevy_sprite = "0.13"
#bevy_prototype_debug_lines = { version = "0.7", features = [ "3d" ] } #bevy_prototype_debug_lines = { version = "0.7", features = [ "3d" ] }
# Dependencies for native only. # Dependencies for native only.
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
bevy = {version = "0.12", default-features = false, features = ["bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} bevy = { version = "0.13", default-features = false, features = ["bevy_winit", "x11", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"] }
# Dependencies for WASM only. # Dependencies for WASM only.
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
bevy = {version = "0.12", default-features = false, features = ["bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"]} bevy = { version = "0.13", default-features = false, features = ["bevy_winit", "tonemapping_luts", "ktx2", "zstd", "bevy_render", "bevy_pbr", "bevy_gizmos"] }
#bevy_webgl2 = "0.5" #bevy_webgl2 = "0.5"
[dependencies.rapier] [dependencies.rapier]
package = "rapier3d" package = "rapier3d"
path = "../rapier3d" path = "../rapier3d"
version = "0.18.0" version = "0.18.0"
features = [ "serde-serialize", "debug-render", "profiler" ] features = ["serde-serialize", "debug-render", "profiler"]

View File

@@ -138,16 +138,16 @@ pub fn init_world(testbed: &mut Testbed) {
for key in gfx.keys().get_pressed() { for key in gfx.keys().get_pressed() {
match *key { match *key {
KeyCode::Right => { KeyCode::ArrowRight => {
steering = -1.0; steering = -1.0;
} }
KeyCode::Left => { KeyCode::ArrowLeft => {
steering = 1.0; steering = 1.0;
} }
KeyCode::Up => { KeyCode::ArrowUp => {
thrust = -drive_strength; thrust = -drive_strength;
} }
KeyCode::Down => { KeyCode::ArrowDown => {
thrust = drive_strength; thrust = drive_strength;
} }
KeyCode::ShiftRight => { KeyCode::ShiftRight => {

View File

@@ -48,7 +48,7 @@ impl OrbitCameraPlugin {
fn mouse_motion_system( fn mouse_motion_system(
_time: Res<Time>, _time: Res<Time>,
mut mouse_motion_events: EventReader<MouseMotion>, mut mouse_motion_events: EventReader<MouseMotion>,
mouse_button_input: Res<Input<MouseButton>>, mouse_button_input: Res<ButtonInput<MouseButton>>,
mut query: Query<(&mut OrbitCamera, &mut Transform, &mut Camera)>, mut query: Query<(&mut OrbitCamera, &mut Transform, &mut Camera)>,
) { ) {
let mut delta = Vec2::ZERO; let mut delta = Vec2::ZERO;

View File

@@ -61,7 +61,7 @@ impl OrbitCameraPlugin {
fn mouse_motion_system( fn mouse_motion_system(
time: Res<Time>, time: Res<Time>,
mut mouse_motion_events: EventReader<MouseMotion>, mut mouse_motion_events: EventReader<MouseMotion>,
mouse_button_input: Res<Input<MouseButton>>, mouse_button_input: Res<ButtonInput<MouseButton>>,
mut query: Query<(&mut OrbitCamera, &mut Transform, &mut Camera)>, mut query: Query<(&mut OrbitCamera, &mut Transform, &mut Camera)>,
) { ) {
let mut delta = Vec2::ZERO; let mut delta = Vec2::ZERO;

View File

@@ -30,11 +30,11 @@ impl Plugin for RapierDebugRenderPlugin {
} }
} }
struct BevyLinesRenderBackend<'a> { struct BevyLinesRenderBackend<'w, 's> {
gizmos: Gizmos<'a>, gizmos: Gizmos<'w, 's>,
} }
impl<'a> DebugRenderBackend for BevyLinesRenderBackend<'a> { impl<'w, 's> DebugRenderBackend for BevyLinesRenderBackend<'w, 's> {
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
fn draw_line(&mut self, _: DebugRenderObject, a: Point<Real>, b: Point<Real>, color: [f32; 4]) { fn draw_line(&mut self, _: DebugRenderObject, a: Point<Real>, b: Point<Real>, color: [f32; 4]) {
self.gizmos.line( self.gizmos.line(

View File

@@ -22,6 +22,9 @@ pub type BevyMaterial = ColorMaterial;
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
pub type BevyMaterial = StandardMaterial; pub type BevyMaterial = StandardMaterial;
pub type InstancedMaterials = HashMap<Point3<usize>, Handle<BevyMaterial>>;
pub const SELECTED_OBJECT_MATERIAL_KEY: Point3<usize> = point![42, 42, 42];
pub struct GraphicsManager { pub struct GraphicsManager {
rand: Pcg32, rand: Pcg32,
b2sn: HashMap<RigidBodyHandle, Vec<EntityWithGraphics>>, b2sn: HashMap<RigidBodyHandle, Vec<EntityWithGraphics>>,
@@ -30,6 +33,7 @@ pub struct GraphicsManager {
b2wireframe: HashMap<RigidBodyHandle, bool>, b2wireframe: HashMap<RigidBodyHandle, bool>,
ground_color: Point3<f32>, ground_color: Point3<f32>,
prefab_meshes: HashMap<ShapeType, Handle<Mesh>>, prefab_meshes: HashMap<ShapeType, Handle<Mesh>>,
instanced_materials: InstancedMaterials,
pub gfx_shift: Vector<Real>, pub gfx_shift: Vector<Real>,
} }
@@ -43,10 +47,15 @@ impl GraphicsManager {
ground_color: point![0.5, 0.5, 0.5], ground_color: point![0.5, 0.5, 0.5],
b2wireframe: HashMap::new(), b2wireframe: HashMap::new(),
prefab_meshes: HashMap::new(), prefab_meshes: HashMap::new(),
instanced_materials: HashMap::new(),
gfx_shift: Vector::zeros(), gfx_shift: Vector::zeros(),
} }
} }
pub fn selection_material(&self) -> Handle<BevyMaterial> {
self.instanced_materials[&SELECTED_OBJECT_MATERIAL_KEY].clone_weak()
}
pub fn clear(&mut self, commands: &mut Commands) { pub fn clear(&mut self, commands: &mut Commands) {
for sns in self.b2sn.values_mut() { for sns in self.b2sn.values_mut() {
for sn in sns.iter_mut() { for sn in sns.iter_mut() {
@@ -54,6 +63,7 @@ impl GraphicsManager {
} }
} }
self.instanced_materials.clear();
self.b2sn.clear(); self.b2sn.clear();
self.c2color.clear(); self.c2color.clear();
self.b2color.clear(); self.b2color.clear();
@@ -159,10 +169,11 @@ impl GraphicsManager {
fn gen_color(rng: &mut Pcg32) -> Point3<f32> { fn gen_color(rng: &mut Pcg32) -> Point3<f32> {
let mut color: Point3<f32> = rng.gen(); let mut color: Point3<f32> = rng.gen();
color *= 1.5;
color.x = color.x.min(1.0); // Quantize the colors a bit to get some amount of auto-instancing from bevy.
color.y = color.y.min(1.0); color.x = (color.x * 5.0).round() / 5.0;
color.z = color.z.min(1.0); color.y = (color.y * 5.0).round() / 5.0;
color.z = (color.z * 5.0).round() / 5.0;
color color
} }
@@ -191,7 +202,7 @@ impl GraphicsManager {
commands: &mut Commands, commands: &mut Commands,
meshes: &mut Assets<Mesh>, meshes: &mut Assets<Mesh>,
materials: &mut Assets<BevyMaterial>, materials: &mut Assets<BevyMaterial>,
components: &mut Query<(&mut Transform,)>, components: &mut Query<&mut Transform>,
handle: RigidBodyHandle, handle: RigidBodyHandle,
bodies: &RigidBodySet, bodies: &RigidBodySet,
colliders: &ColliderSet, colliders: &ColliderSet,
@@ -214,7 +225,7 @@ impl GraphicsManager {
commands: &mut Commands, commands: &mut Commands,
meshes: &mut Assets<Mesh>, meshes: &mut Assets<Mesh>,
materials: &mut Assets<BevyMaterial>, materials: &mut Assets<BevyMaterial>,
components: &mut Query<(&mut Transform,)>, components: &mut Query<&mut Transform>,
handle: RigidBodyHandle, handle: RigidBodyHandle,
bodies: &RigidBodySet, bodies: &RigidBodySet,
colliders: &ColliderSet, colliders: &ColliderSet,
@@ -330,6 +341,7 @@ impl GraphicsManager {
meshes, meshes,
materials, materials,
&self.prefab_meshes, &self.prefab_meshes,
&mut self.instanced_materials,
shape, shape,
handle, handle,
*pos, *pos,
@@ -345,7 +357,7 @@ impl GraphicsManager {
&mut self, &mut self,
_bodies: &RigidBodySet, _bodies: &RigidBodySet,
colliders: &ColliderSet, colliders: &ColliderSet,
components: &mut Query<(&mut Transform,)>, components: &mut Query<&mut Transform>,
_materials: &mut Assets<BevyMaterial>, _materials: &mut Assets<BevyMaterial>,
) { ) {
for (_, ns) in self.b2sn.iter_mut() { for (_, ns) in self.b2sn.iter_mut() {

View File

@@ -14,7 +14,7 @@ use rapier::geometry::{ColliderHandle, ColliderSet, Shape, ShapeType};
use rapier::geometry::{Cone, Cylinder}; use rapier::geometry::{Cone, Cylinder};
use rapier::math::{Isometry, Real, Vector}; use rapier::math::{Isometry, Real, Vector};
use crate::graphics::BevyMaterial; use crate::graphics::{BevyMaterial, InstancedMaterials, SELECTED_OBJECT_MATERIAL_KEY};
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
use { use {
bevy_sprite::MaterialMesh2dBundle, bevy_sprite::MaterialMesh2dBundle,
@@ -30,15 +30,43 @@ pub struct EntityWithGraphics {
pub collider: Option<ColliderHandle>, pub collider: Option<ColliderHandle>,
pub delta: Isometry<Real>, pub delta: Isometry<Real>,
pub opacity: f32, pub opacity: f32,
material: Handle<BevyMaterial>, pub material: Handle<BevyMaterial>,
} }
impl EntityWithGraphics { impl EntityWithGraphics {
pub fn register_selected_object_material(
materials: &mut Assets<BevyMaterial>,
instanced_materials: &mut InstancedMaterials,
) {
if instanced_materials.contains_key(&SELECTED_OBJECT_MATERIAL_KEY) {
return; // Already added.
}
#[cfg(feature = "dim2")]
let selection_material = ColorMaterial {
color: Color::rgb(1.0, 0.0, 0.0),
texture: None,
};
#[cfg(feature = "dim3")]
let selection_material = StandardMaterial {
metallic: 0.5,
perceptual_roughness: 0.5,
double_sided: true, // TODO: this doesn't do anything?
..StandardMaterial::from(Color::rgb(1.0, 0.0, 0.0))
};
instanced_materials.insert(
SELECTED_OBJECT_MATERIAL_KEY,
materials.add(selection_material),
);
}
pub fn spawn( pub fn spawn(
commands: &mut Commands, commands: &mut Commands,
meshes: &mut Assets<Mesh>, meshes: &mut Assets<Mesh>,
materials: &mut Assets<BevyMaterial>, materials: &mut Assets<BevyMaterial>,
prefab_meshs: &HashMap<ShapeType, Handle<Mesh>>, prefab_meshs: &HashMap<ShapeType, Handle<Mesh>>,
instanced_materials: &mut InstancedMaterials,
shape: &dyn Shape, shape: &dyn Shape,
collider: Option<ColliderHandle>, collider: Option<ColliderHandle>,
collider_pos: Isometry<Real>, collider_pos: Isometry<Real>,
@@ -46,6 +74,8 @@ impl EntityWithGraphics {
color: Point3<f32>, color: Point3<f32>,
sensor: bool, sensor: bool,
) -> Self { ) -> Self {
Self::register_selected_object_material(materials, instanced_materials);
let entity = commands.spawn_empty().id(); let entity = commands.spawn_empty().id();
let scale = collider_mesh_scale(shape); let scale = collider_mesh_scale(shape);
@@ -90,21 +120,23 @@ impl EntityWithGraphics {
double_sided: true, // TODO: this doesn't do anything? double_sided: true, // TODO: this doesn't do anything?
..StandardMaterial::from(bevy_color) ..StandardMaterial::from(bevy_color)
}; };
let material_handle = materials.add(material); let material_handle = instanced_materials
.entry(color.coords.map(|c| (c * 255.0) as usize).into())
.or_insert_with(|| materials.add(material));
let material_weak_handle = material_handle.clone_weak(); let material_weak_handle = material_handle.clone_weak();
if let Some(mesh) = mesh { if let Some(mesh) = mesh {
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
let bundle = MaterialMesh2dBundle { let bundle = MaterialMesh2dBundle {
mesh: mesh.into(), mesh: mesh.into(),
material: material_handle, material: material_handle.clone_weak(),
transform, transform,
..Default::default() ..Default::default()
}; };
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
let bundle = PbrBundle { let bundle = PbrBundle {
mesh, mesh,
material: material_handle, material: material_handle.clone_weak(),
transform, transform,
..Default::default() ..Default::default()
}; };
@@ -133,28 +165,6 @@ impl EntityWithGraphics {
commands.entity(self.entity).despawn(); commands.entity(self.entity).despawn();
} }
pub fn select(&mut self, materials: &mut Assets<BevyMaterial>) {
// NOTE: we don't just call `self.set_color` because that would
// overwrite self.base_color too.
self.color = point![1.0, 0.0, 0.0];
if let Some(material) = materials.get_mut(&self.material) {
#[cfg(feature = "dim2")]
{
material.color =
Color::rgba(self.color.x, self.color.y, self.color.z, self.opacity);
}
#[cfg(feature = "dim3")]
{
material.base_color =
Color::rgba(self.color.x, self.color.y, self.color.z, self.opacity);
}
}
}
pub fn unselect(&mut self, materials: &mut Assets<BevyMaterial>) {
self.set_color(materials, self.base_color);
}
pub fn set_color(&mut self, materials: &mut Assets<BevyMaterial>, color: Point3<f32>) { pub fn set_color(&mut self, materials: &mut Assets<BevyMaterial>, color: Point3<f32>) {
if let Some(material) = materials.get_mut(&self.material) { if let Some(material) = materials.get_mut(&self.material) {
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
@@ -173,11 +183,11 @@ impl EntityWithGraphics {
pub fn update( pub fn update(
&mut self, &mut self,
colliders: &ColliderSet, colliders: &ColliderSet,
components: &mut Query<(&mut Transform,)>, components: &mut Query<&mut Transform>,
gfx_shift: &Vector<Real>, gfx_shift: &Vector<Real>,
) { ) {
if let Some(Some(co)) = self.collider.map(|c| colliders.get(c)) { if let Some(Some(co)) = self.collider.map(|c| colliders.get(c)) {
if let Ok(mut pos) = components.get_component_mut::<Transform>(self.entity) { if let Ok(mut pos) = components.get_mut(self.entity) {
let co_pos = co.position() * self.delta; let co_pos = co.position() * self.delta;
pos.translation.x = (co_pos.translation.vector.x + gfx_shift.x) as f32; pos.translation.x = (co_pos.translation.vector.x + gfx_shift.x) as f32;
pos.translation.y = (co_pos.translation.vector.y + gfx_shift.y) as f32; pos.translation.y = (co_pos.translation.vector.y + gfx_shift.y) as f32;
@@ -230,18 +240,14 @@ impl EntityWithGraphics {
// //
// Cuboid mesh // Cuboid mesh
// //
let cuboid = Mesh::from(shape::Cube { size: 2.0 }); let cuboid = Mesh::from(bevy::math::primitives::Cuboid::new(2.0, 2.0, 2.0));
out.insert(ShapeType::Cuboid, meshes.add(cuboid.clone())); out.insert(ShapeType::Cuboid, meshes.add(cuboid.clone()));
out.insert(ShapeType::RoundCuboid, meshes.add(cuboid)); out.insert(ShapeType::RoundCuboid, meshes.add(cuboid));
// //
// Ball mesh // Ball mesh
// //
let ball = Mesh::try_from(shape::Icosphere { let ball = Mesh::try_from(bevy::math::primitives::Sphere::new(1.0)).unwrap();
subdivisions: 2,
radius: 1.0,
})
.unwrap();
out.insert(ShapeType::Ball, meshes.add(ball)); out.insert(ShapeType::Ball, meshes.add(ball));
// //
@@ -309,14 +315,14 @@ fn bevy_polyline(buffers: (Vec<Point2<Real>>, Option<Vec<[u32; 2]>>)) -> Mesh {
let normals: Vec<_> = (0..vertices.len()).map(|_| [0.0, 0.0, 1.0]).collect(); let normals: Vec<_> = (0..vertices.len()).map(|_| [0.0, 0.0, 1.0]).collect();
// Generate the mesh // Generate the mesh
let mut mesh = Mesh::new(PrimitiveTopology::LineStrip); let mut mesh = Mesh::new(PrimitiveTopology::LineStrip, Default::default());
mesh.insert_attribute( mesh.insert_attribute(
Mesh::ATTRIBUTE_POSITION, Mesh::ATTRIBUTE_POSITION,
VertexAttributeValues::from(vertices), VertexAttributeValues::from(vertices),
); );
mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, VertexAttributeValues::from(normals)); mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, VertexAttributeValues::from(normals));
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, VertexAttributeValues::from(uvs)); mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, VertexAttributeValues::from(uvs));
mesh.set_indices(Some(Indices::U32(indices))); mesh.insert_indices(Indices::U32(indices));
mesh mesh
} }
@@ -352,14 +358,14 @@ fn bevy_mesh(buffers: (Vec<Point3<Real>>, Vec<[u32; 3]>)) -> Mesh {
let uvs: Vec<_> = (0..vertices.len()).map(|_| [0.0, 0.0]).collect(); let uvs: Vec<_> = (0..vertices.len()).map(|_| [0.0, 0.0]).collect();
// Generate the mesh // Generate the mesh
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList); let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, Default::default());
mesh.insert_attribute( mesh.insert_attribute(
Mesh::ATTRIBUTE_POSITION, Mesh::ATTRIBUTE_POSITION,
VertexAttributeValues::from(vertices), VertexAttributeValues::from(vertices),
); );
mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, VertexAttributeValues::from(normals)); mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, VertexAttributeValues::from(normals));
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, VertexAttributeValues::from(uvs)); mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, VertexAttributeValues::from(uvs));
mesh.set_indices(Some(Indices::U32(indices))); mesh.insert_indices(Indices::U32(indices));
mesh mesh
} }

View File

@@ -14,7 +14,7 @@ pub trait TestbedPlugin {
commands: &mut Commands, commands: &mut Commands,
meshes: &mut Assets<Mesh>, meshes: &mut Assets<Mesh>,
materials: &mut Assets<BevyMaterial>, materials: &mut Assets<BevyMaterial>,
components: &mut Query<(&mut Transform,)>, components: &mut Query<&mut Transform>,
harness: &mut Harness, harness: &mut Harness,
); );
fn clear_graphics(&mut self, graphics: &mut GraphicsManager, commands: &mut Commands); fn clear_graphics(&mut self, graphics: &mut GraphicsManager, commands: &mut Commands);
@@ -26,7 +26,7 @@ pub trait TestbedPlugin {
commands: &mut Commands, commands: &mut Commands,
meshes: &mut Assets<Mesh>, meshes: &mut Assets<Mesh>,
materials: &mut Assets<BevyMaterial>, materials: &mut Assets<BevyMaterial>,
components: &mut Query<(&mut Transform,)>, components: &mut Query<&mut Transform>,
harness: &mut Harness, harness: &mut Harness,
); );
fn update_ui( fn update_ui(
@@ -37,7 +37,7 @@ pub trait TestbedPlugin {
commands: &mut Commands, commands: &mut Commands,
meshes: &mut Assets<Mesh>, meshes: &mut Assets<Mesh>,
materials: &mut Assets<BevyMaterial>, materials: &mut Assets<BevyMaterial>,
components: &mut Query<(&mut Transform,)>, components: &mut Query<&mut Transform>,
); );
fn profiling_string(&self) -> String; fn profiling_string(&self) -> String;
} }

View File

@@ -31,8 +31,7 @@ use crate::box2d_backend::Box2dWorld;
use crate::harness::Harness; use crate::harness::Harness;
#[cfg(all(feature = "dim3", feature = "other-backends"))] #[cfg(all(feature = "dim3", feature = "other-backends"))]
use crate::physx_backend::PhysxWorld; use crate::physx_backend::PhysxWorld;
use bevy::render::camera::Camera; use bevy::render::camera::{Camera, ClearColor};
use bevy_core_pipeline::prelude::ClearColor;
use bevy_egui::EguiContexts; use bevy_egui::EguiContexts;
use bevy_pbr::wireframe::WireframePlugin; use bevy_pbr::wireframe::WireframePlugin;
use bevy_pbr::AmbientLight; use bevy_pbr::AmbientLight;
@@ -155,11 +154,11 @@ pub struct TestbedGraphics<'a, 'b, 'c, 'd, 'e, 'f> {
commands: &'a mut Commands<'d, 'e>, commands: &'a mut Commands<'d, 'e>,
meshes: &'a mut Assets<Mesh>, meshes: &'a mut Assets<Mesh>,
materials: &'a mut Assets<BevyMaterial>, materials: &'a mut Assets<BevyMaterial>,
components: &'a mut Query<'b, 'f, (&'c mut Transform,)>, components: &'a mut Query<'b, 'f, &'c mut Transform>,
#[allow(dead_code)] // Dead in 2D but not in 3D. #[allow(dead_code)] // Dead in 2D but not in 3D.
camera_transform: GlobalTransform, camera_transform: GlobalTransform,
camera: &'a mut OrbitCamera, camera: &'a mut OrbitCamera,
keys: &'a Input<KeyCode>, keys: &'a ButtonInput<KeyCode>,
} }
pub struct Testbed<'a, 'b, 'c, 'd, 'e, 'f> { pub struct Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
@@ -468,7 +467,7 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> TestbedGraphics<'a, 'b, 'c, 'd, 'e, 'f> {
) )
} }
pub fn keys(&self) -> &Input<KeyCode> { pub fn keys(&self) -> &ButtonInput<KeyCode> {
self.keys self.keys
} }
} }
@@ -660,7 +659,7 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
} }
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
fn update_vehicle_controller(&mut self, events: &Input<KeyCode>) { fn update_vehicle_controller(&mut self, events: &ButtonInput<KeyCode>) {
if self.state.running == RunMode::Stop { if self.state.running == RunMode::Stop {
return; return;
} }
@@ -671,16 +670,16 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
for key in events.get_pressed() { for key in events.get_pressed() {
match *key { match *key {
KeyCode::Right => { KeyCode::ArrowRight => {
steering_angle += -0.7; steering_angle += -0.7;
} }
KeyCode::Left => { KeyCode::ArrowLeft => {
steering_angle += 0.7; steering_angle += 0.7;
} }
KeyCode::Up => { KeyCode::ArrowUp => {
engine_force += 30.0; engine_force += 30.0;
} }
KeyCode::Down => { KeyCode::ArrowDown => {
engine_force += -30.0; engine_force += -30.0;
} }
_ => {} _ => {}
@@ -703,7 +702,7 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
} }
} }
fn update_character_controller(&mut self, events: &Input<KeyCode>) { fn update_character_controller(&mut self, events: &ButtonInput<KeyCode>) {
if self.state.running == RunMode::Stop { if self.state.running == RunMode::Stop {
return; return;
} }
@@ -715,10 +714,10 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
for key in events.get_pressed() { for key in events.get_pressed() {
match *key { match *key {
KeyCode::Right => { KeyCode::ArrowRight => {
desired_movement += Vector::x(); desired_movement += Vector::x();
} }
KeyCode::Left => { KeyCode::ArrowLeft => {
desired_movement -= Vector::x(); desired_movement -= Vector::x();
} }
KeyCode::Space => { KeyCode::Space => {
@@ -750,16 +749,16 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
for key in events.get_pressed() { for key in events.get_pressed() {
match *key { match *key {
KeyCode::Right => { KeyCode::ArrowRight => {
desired_movement += rot_x; desired_movement += rot_x;
} }
KeyCode::Left => { KeyCode::ArrowLeft => {
desired_movement -= rot_x; desired_movement -= rot_x;
} }
KeyCode::Up => { KeyCode::ArrowUp => {
desired_movement -= rot_z; desired_movement -= rot_z;
} }
KeyCode::Down => { KeyCode::ArrowDown => {
desired_movement += rot_z; desired_movement += rot_z;
} }
KeyCode::Space => { KeyCode::Space => {
@@ -818,22 +817,22 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
} }
} }
fn handle_common_events(&mut self, events: &Input<KeyCode>) { fn handle_common_events(&mut self, events: &ButtonInput<KeyCode>) {
for key in events.get_just_released() { for key in events.get_just_released() {
match *key { match *key {
KeyCode::T => { KeyCode::KeyT => {
if self.state.running == RunMode::Stop { if self.state.running == RunMode::Stop {
self.state.running = RunMode::Running; self.state.running = RunMode::Running;
} else { } else {
self.state.running = RunMode::Stop; self.state.running = RunMode::Stop;
} }
} }
KeyCode::S => self.state.running = RunMode::Step, KeyCode::KeyS => self.state.running = RunMode::Step,
KeyCode::R => self KeyCode::KeyR => self
.state .state
.action_flags .action_flags
.set(TestbedActionFlags::EXAMPLE_CHANGED, true), .set(TestbedActionFlags::EXAMPLE_CHANGED, true),
KeyCode::C => { KeyCode::KeyC => {
// Delete 1 collider of 10% of the remaining dynamic bodies. // Delete 1 collider of 10% of the remaining dynamic bodies.
let mut colliders: Vec<_> = self let mut colliders: Vec<_> = self
.harness .harness
@@ -859,7 +858,7 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
); );
} }
} }
KeyCode::D => { KeyCode::KeyD => {
// Delete 10% of the remaining dynamic bodies. // Delete 10% of the remaining dynamic bodies.
let dynamic_bodies: Vec<_> = self let dynamic_bodies: Vec<_> = self
.harness .harness
@@ -884,7 +883,7 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
); );
} }
} }
KeyCode::J => { KeyCode::KeyJ => {
// Delete 10% of the remaining impulse_joints. // Delete 10% of the remaining impulse_joints.
let impulse_joints: Vec<_> = self let impulse_joints: Vec<_> = self
.harness .harness
@@ -898,7 +897,7 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
self.harness.physics.impulse_joints.remove(*to_delete, true); self.harness.physics.impulse_joints.remove(*to_delete, true);
} }
} }
KeyCode::A => { KeyCode::KeyA => {
// Delete 10% of the remaining multibody_joints. // Delete 10% of the remaining multibody_joints.
let multibody_joints: Vec<_> = self let multibody_joints: Vec<_> = self
.harness .harness
@@ -915,7 +914,7 @@ impl<'a, 'b, 'c, 'd, 'e, 'f> Testbed<'a, 'b, 'c, 'd, 'e, 'f> {
.remove(*to_delete, true); .remove(*to_delete, true);
} }
} }
KeyCode::M => { KeyCode::KeyM => {
// Delete one remaining multibody. // Delete one remaining multibody.
let to_delete = self let to_delete = self
.harness .harness
@@ -1013,10 +1012,14 @@ fn draw_contacts(_nf: &NarrowPhase, _colliders: &ColliderSet) {
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
fn setup_graphics_environment(mut commands: Commands) { fn setup_graphics_environment(mut commands: Commands) {
commands.insert_resource(AmbientLight {
brightness: 100.0,
..Default::default()
});
commands.spawn(DirectionalLightBundle { commands.spawn(DirectionalLightBundle {
directional_light: DirectionalLight { directional_light: DirectionalLight {
illuminance: 10000.0, shadows_enabled: false,
shadows_enabled: true,
..Default::default() ..Default::default()
}, },
transform: Transform { transform: Transform {
@@ -1102,9 +1105,10 @@ fn update_testbed(
#[cfg(feature = "other-backends")] mut other_backends: NonSendMut<OtherBackends>, #[cfg(feature = "other-backends")] mut other_backends: NonSendMut<OtherBackends>,
mut plugins: NonSendMut<Plugins>, mut plugins: NonSendMut<Plugins>,
mut ui_context: EguiContexts, mut ui_context: EguiContexts,
mut gfx_components: Query<(&mut Transform,)>, mut gfx_components: Query<&mut Transform>,
mut cameras: Query<(&Camera, &GlobalTransform, &mut OrbitCamera)>, mut cameras: Query<(&Camera, &GlobalTransform, &mut OrbitCamera)>,
keys: Res<Input<KeyCode>>, mut material_handles: Query<&mut Handle<BevyMaterial>>,
keys: Res<ButtonInput<KeyCode>>,
) { ) {
let meshes = &mut *meshes; let meshes = &mut *meshes;
let materials = &mut *materials; let materials = &mut *materials;
@@ -1448,7 +1452,7 @@ fn update_testbed(
if let Ok(window) = windows.get_single() { if let Ok(window) = windows.get_single() {
for (camera, camera_pos, _) in cameras.iter_mut() { for (camera, camera_pos, _) in cameras.iter_mut() {
highlight_hovered_body( highlight_hovered_body(
&mut *materials, &mut material_handles,
&mut graphics, &mut graphics,
&mut state, &mut state,
&harness.physics, &harness.physics,
@@ -1502,7 +1506,7 @@ fn clear(
#[cfg(feature = "dim2")] #[cfg(feature = "dim2")]
fn highlight_hovered_body( fn highlight_hovered_body(
_materials: &mut Assets<BevyMaterial>, _material_handles: &mut Query<&mut Handle<BevyMaterial>>,
_graphics_manager: &mut GraphicsManager, _graphics_manager: &mut GraphicsManager,
_testbed_state: &mut TestbedState, _testbed_state: &mut TestbedState,
_physics: &PhysicsState, _physics: &PhysicsState,
@@ -1515,7 +1519,7 @@ fn highlight_hovered_body(
#[cfg(feature = "dim3")] #[cfg(feature = "dim3")]
fn highlight_hovered_body( fn highlight_hovered_body(
materials: &mut Assets<BevyMaterial>, material_handles: &mut Query<&mut Handle<BevyMaterial>>,
graphics_manager: &mut GraphicsManager, graphics_manager: &mut GraphicsManager,
testbed_state: &mut TestbedState, testbed_state: &mut TestbedState,
physics: &PhysicsState, physics: &PhysicsState,
@@ -1526,7 +1530,9 @@ fn highlight_hovered_body(
if let Some(highlighted_body) = testbed_state.highlighted_body { if let Some(highlighted_body) = testbed_state.highlighted_body {
if let Some(nodes) = graphics_manager.body_nodes_mut(highlighted_body) { if let Some(nodes) = graphics_manager.body_nodes_mut(highlighted_body) {
for node in nodes { for node in nodes {
node.unselect(materials) if let Ok(mut handle) = material_handles.get_mut(node.entity) {
*handle = node.material.clone_weak()
};
} }
} }
} }
@@ -1558,8 +1564,12 @@ fn highlight_hovered_body(
if let Some(parent_handle) = collider.parent() { if let Some(parent_handle) = collider.parent() {
testbed_state.highlighted_body = Some(parent_handle); testbed_state.highlighted_body = Some(parent_handle);
let selection_material = graphics_manager.selection_material();
for node in graphics_manager.body_nodes_mut(parent_handle).unwrap() { for node in graphics_manager.body_nodes_mut(parent_handle).unwrap() {
node.select(materials) if let Ok(mut handle) = material_handles.get_mut(node.entity) {
*handle = selection_material.clone_weak();
}
} }
} }
} }