add direct access to gear data
authoralfadur
Fri, 28 Jan 2022 02:33:44 +0300
changeset 15829 d5e6c8c92d87
parent 15828 44b49f255e31
child 15830 ea459da15b30
add direct access to gear data
rust/hwphysics/src/data.rs
rust/hwphysics/src/lib.rs
--- a/rust/hwphysics/src/data.rs	Thu Jan 27 03:51:13 2022 +0300
+++ b/rust/hwphysics/src/data.rs	Fri Jan 28 02:33:44 2022 +0300
@@ -242,7 +242,7 @@
             block_masks: vec![],
             element_sizes: Box::new([0; 64]),
             element_alignments: Box::new([0; 64]),
-            lookup: vec![LookupEntry::default(); u16::max_value() as usize].into_boxed_slice(),
+            lookup: vec![LookupEntry::default(); u16::MAX as usize].into_boxed_slice(),
         }
     }
 
@@ -486,7 +486,7 @@
 
     pub fn register<T: 'static>(&mut self) {
         debug_assert!(!std::mem::needs_drop::<T>());
-        debug_assert!(size_of::<T>() <= u16::max_value() as usize);
+        debug_assert!(size_of::<T>() <= u16::MAX as usize);
 
         let id = TypeId::of::<T>();
         if size_of::<T>() == 0 {
@@ -533,6 +533,19 @@
         }
     }
 
+    pub fn get<T: 'static>(&self, gear_id: GearId) -> Option<&T> {
+        let entry = self.lookup[gear_id.get() as usize - 1];
+        match (entry.index, self.get_type_index::<T>()) {
+            (Some(index), Some(type_index)) => {
+                let block = &self.blocks[entry.block_index as usize];
+                block.component_blocks[type_index].map(|ptr| unsafe {
+                    &*(ptr.as_ptr() as *const T).add(index.get() as usize - 1)
+                })
+            }
+            _ => None,
+        }
+    }
+
     pub fn iter<T: TypeIter + 'static>(&mut self) -> DataIterator<T> {
         let mut arg_types = Vec::with_capacity(64);
         T::get_types(&mut arg_types);
@@ -614,6 +627,25 @@
     struct Tag;
 
     #[test]
+    fn direct_access() {
+        let mut manager = GearDataManager::new();
+        manager.register::<Datum>();
+        for i in 1..=5 {
+            manager.add(GearId::new(i as u16).unwrap(), &Datum { value: i * i });
+        }
+
+        for i in 1..=5 {
+            assert_eq!(
+                manager
+                    .get::<Datum>(GearId::new(i as u16).unwrap())
+                    .unwrap()
+                    .value,
+                i * i
+            );
+        }
+    }
+
+    #[test]
     fn single_component_iteration() {
         let mut manager = GearDataManager::new();
         manager.register::<Datum>();
--- a/rust/hwphysics/src/lib.rs	Thu Jan 27 03:51:13 2022 +0300
+++ b/rust/hwphysics/src/lib.rs	Fri Jan 28 02:33:44 2022 +0300
@@ -6,7 +6,10 @@
 
 use integral_geometry::PotSize;
 use land2d::Land2D;
+use std::any::{Any, TypeId};
 
+use crate::collision::CollisionData;
+use crate::physics::VelocityData;
 use crate::{
     collision::CollisionProcessor,
     common::{GearAllocator, GearId, Millis},
@@ -52,9 +55,20 @@
         let collisions = self.collision.process(land, &updates);
     }
 
-    #[inline]
     pub fn add_gear_data<T: Clone + 'static>(&mut self, gear_id: GearId, data: &T) {
         self.data.add(gear_id, data);
+        if TypeId::of::<T>() == TypeId::of::<VelocityData>() {
+            self.collision.remove(gear_id);
+        }
+    }
+
+    pub fn remove_gear_data<T: Clone + 'static>(&mut self, gear_id: GearId) {
+        self.data.remove::<T>(gear_id);
+        if TypeId::of::<T>() == TypeId::of::<VelocityData>() {
+            if let Some(collision_data) = self.data.get::<CollisionData>(gear_id) {
+                self.collision.add(gear_id, *collision_data);
+            }
+        }
     }
 
     #[inline]
@@ -72,12 +86,12 @@
         World,
     };
     use fpnum::{fp, FPNum, FPPoint};
-    use integral_geometry::PotSize;
+    use integral_geometry::{PotSize, Size};
     use land2d::Land2D;
 
     #[test]
     fn data_flow() {
-        let world_size = PotSize::new(2048, 2048).unwrap;
+        let world_size = PotSize::new(2048, 2048).unwrap();
 
         let mut world = World::new(world_size);
         let gear_id = world.new_gear().unwrap();
@@ -95,7 +109,10 @@
             },
         );
 
-        let land = Land2D::new(Size::new(world_size.width - 2, world_size.height - 2), 0);
+        let land = Land2D::new(
+            Size::new(world_size.width() - 2, world_size.height() - 2),
+            0,
+        );
 
         world.step(Millis::new(1), &land);
     }