diff --git a/examples2d/balls2.rs b/examples2d/balls2.rs index 738fefe7d..b8f4ea20b 100644 --- a/examples2d/balls2.rs +++ b/examples2d/balls2.rs @@ -9,8 +9,7 @@ use nphysics2d::object::{BodyHandle, Material}; use nphysics2d::volumetric::Volumetric; use nphysics2d::world::World; use nphysics_testbed2d::Testbed; -use std::sync::Arc; -use std::sync::Mutex; +use nphysics_testbed2d::WorldOwnerExclusive; const COLLIDER_MARGIN: f32 = 0.01; @@ -82,7 +81,7 @@ fn main() { /* * Set up the testbed. */ - let mut testbed = Testbed::new(Arc::new(Mutex::new(world))); + let mut testbed = Testbed::new(Box::new(WorldOwnerExclusive::new(world))); testbed.look_at(Point2::new(0.0, -2.5), 95.0); testbed.run(); } diff --git a/nphysics_testbed2d/src/lib.rs b/nphysics_testbed2d/src/lib.rs index d8f9915e5..828ceac80 100644 --- a/nphysics_testbed2d/src/lib.rs +++ b/nphysics_testbed2d/src/lib.rs @@ -8,6 +8,9 @@ extern crate time; pub use engine::GraphicsManager; pub use testbed::Testbed; +pub use testbed::WorldOwner; +pub use testbed::WorldOwnerShared; +pub use testbed::WorldOwnerExclusive; mod engine; pub mod objects; diff --git a/nphysics_testbed2d/src/testbed.rs b/nphysics_testbed2d/src/testbed.rs index b533edbe5..f324dcaad 100644 --- a/nphysics_testbed2d/src/testbed.rs +++ b/nphysics_testbed2d/src/testbed.rs @@ -19,6 +19,7 @@ use std::path::Path; use std::rc::Rc; use std::sync::Arc; use std::sync::Mutex; +use std::ops::DerefMut; #[derive(PartialEq)] enum RunMode { @@ -51,8 +52,45 @@ fn usage(exe_name: &str) { println!(" b - draw the bounding boxes."); } -pub struct Testbed { +/// This trait is designed to allow choosing implementation of underlying storing of World: shared between threads or owned only by WorldOwner. +pub trait WorldOwner { + fn get_mut<'a: 'b, 'b>(&'a mut self) -> Box> + 'b>; +} + +#[derive(Clone)] +pub struct WorldOwnerShared { world: Arc>>, +} + +impl WorldOwnerShared { + pub fn new(w: World) -> WorldOwnerShared { + WorldOwnerShared {world: Arc::new(Mutex::new(w))} + } +} + +impl WorldOwner for WorldOwnerShared { + fn get_mut<'a: 'b, 'b>(&'a mut self) -> Box> + 'b> { + Box::new(self.world.lock().unwrap()) + } +} + +pub struct WorldOwnerExclusive { + world: World +} + +impl WorldOwnerExclusive { + pub fn new(world: World) -> WorldOwnerExclusive { + WorldOwnerExclusive {world} + } +} + +impl WorldOwner for WorldOwnerExclusive { + fn get_mut<'a: 'b, 'b>(&'a mut self) -> Box> + 'b> { + Box::new(&mut self.world) + } +} + +pub struct Testbed { window: Option>, graphics: GraphicsManager, nsteps: usize, @@ -67,6 +105,7 @@ pub struct Testbed { cursor_pos: Point2, grabbed_object: Option, grabbed_object_constraint: Option, + world: Box, } impl Testbed { @@ -79,7 +118,7 @@ impl Testbed { window.set_framerate_limit(Some(60)); Testbed { - world: Arc::new(Mutex::new(world)), + world: Box::new(WorldOwnerShared::new(world)), callbacks: Vec::new(), window: Some(window), graphics: graphics, @@ -97,7 +136,7 @@ impl Testbed { } } - pub fn new(world: Arc>>) -> Testbed { + pub fn new(world: Box) -> Testbed { let mut res = Testbed::new_empty(); res.set_world(world); @@ -117,9 +156,9 @@ impl Testbed { self.hide_counters = false; } - pub fn set_world(&mut self, world: Arc>>) { + pub fn set_world(&mut self, world: Box) { self.world = world; - let mut world = self.world.lock().unwrap(); + let mut world = self.world.get_mut(); world.enable_performance_counters(); self.graphics.clear(self.window.as_mut().unwrap()); @@ -142,9 +181,9 @@ impl Testbed { self.graphics.set_collider_color(collider, color); } - /*pub fn world(&self) -> &World { - &self.world.borrow_mut() - }*/ + pub fn world(&self) -> &Box { + &self.world + } pub fn graphics_mut(&mut self) -> &mut GraphicsManager { &mut self.graphics @@ -237,7 +276,7 @@ impl State for Testbed { // graphics.add(window, WorldObject::RigidBody(body)); // }, WindowEvent::MouseButton(_, Action::Press, modifier) => { - let mut physics_world = &mut self.world.lock().unwrap(); + let mut physics_world = &mut self.world.get_mut(); let mapped_point = self .graphics .camera() @@ -310,7 +349,7 @@ impl State for Testbed { } } WindowEvent::MouseButton(_, Action::Release, _) => { - let mut physics_world = &mut self.world.lock().unwrap(); + let mut physics_world = &mut self.world.get_mut(); if let Some(body) = self.grabbed_object { for n in self .graphics @@ -330,7 +369,7 @@ impl State for Testbed { self.grabbed_object_constraint = None; } WindowEvent::CursorPos(x, y, modifiers) => { - let mut physics_world = &mut self.world.lock().unwrap(); + let mut physics_world = &mut self.world.get_mut(); self.cursor_pos.x = x as f32; self.cursor_pos.y = y as f32; @@ -371,7 +410,7 @@ impl State for Testbed { // // } // }, WindowEvent::Key(Key::Space, Action::Release, _) => { - let mut physics_world = &mut self.world.lock().unwrap(); + let mut physics_world = &mut self.world.get_mut(); self.draw_colls = !self.draw_colls; for co in physics_world.colliders() { // FIXME: ugly clone. @@ -443,17 +482,13 @@ impl State for Testbed { for f in &self.callbacks { f(&mut self.graphics, self.time) } - self.world.lock().unwrap().step(); + self.world.get_mut().step(); if !self.hide_counters { - println!("{}", self.world.lock().unwrap().performance_counters()); + println!("{}", self.world.get_mut().performance_counters()); } - self.time += self.world.lock().unwrap().timestep(); + self.time += self.world.get_mut().timestep(); } - } - - // Draw scope - { - let mut physics_world = &mut self.world.lock().unwrap(); + let physics_world = &self.world.get_mut(); for co in physics_world.colliders() { if self.graphics.body_nodes_mut(physics_world, co.data().body()).is_none() { @@ -462,14 +497,15 @@ impl State for Testbed { } } self.graphics.draw(&physics_world, window); - if self.draw_colls { - draw_collisions( - window, - &mut physics_world, - &mut self.persistant_contacts, - self.running != RunMode::Stop, - ); - } + } + + if self.draw_colls { + draw_collisions( + window, + &mut self.world.get_mut(), + &mut self.persistant_contacts, + self.running != RunMode::Stop, + ); } if self.running == RunMode::Step { @@ -484,7 +520,7 @@ impl State for Testbed { &format!( "Simulation time: {:.*}sec.", 4, - self.world.lock().unwrap().performance_counters().step_time(), + self.world.get_mut().performance_counters().step_time(), )[..], &Point2::origin(), 60.0,