8 use integral_geometry::Size; |
8 use integral_geometry::Size; |
9 use land2d::Land2D; |
9 use land2d::Land2D; |
10 |
10 |
11 use crate::{ |
11 use crate::{ |
12 collision::{CollisionData, CollisionProcessor, ContactData}, |
12 collision::{CollisionData, CollisionProcessor, ContactData}, |
13 common::{GearAllocator, GearData, GearDataAggregator, GearDataProcessor, GearId, Millis}, |
13 common::{GearAllocator, GearId, Millis}, |
14 physics::{PhysicsData, PhysicsProcessor}, |
14 data::GearDataManager, |
|
15 physics::PhysicsProcessor, |
15 time::TimeProcessor, |
16 time::TimeProcessor, |
16 }; |
17 }; |
17 |
18 |
18 pub struct JoinedData { |
|
19 gear_id: GearId, |
|
20 physics: PhysicsData, |
|
21 collision: CollisionData, |
|
22 contact: ContactData, |
|
23 } |
|
24 |
|
25 pub struct World { |
19 pub struct World { |
26 allocator: GearAllocator, |
20 allocator: GearAllocator, |
|
21 data: GearDataManager, |
27 physics: PhysicsProcessor, |
22 physics: PhysicsProcessor, |
28 collision: CollisionProcessor, |
23 collision: CollisionProcessor, |
29 time: TimeProcessor, |
24 time: TimeProcessor, |
30 } |
25 } |
31 |
26 |
32 macro_rules! processor_map { |
|
33 ( $data_type: ident => $field: ident ) => { |
|
34 impl GearDataAggregator<$data_type> for World { |
|
35 fn find_processor(&mut self) -> &mut GearDataProcessor<$data_type> { |
|
36 &mut self.$field |
|
37 } |
|
38 } |
|
39 }; |
|
40 } |
|
41 |
|
42 processor_map!(PhysicsData => physics); |
|
43 processor_map!(CollisionData => collision); |
|
44 |
|
45 impl World { |
27 impl World { |
46 pub fn new(world_size: Size) -> Self { |
28 pub fn new(world_size: Size) -> Self { |
|
29 let mut data = GearDataManager::new(); |
|
30 PhysicsProcessor::register_components(&mut data); |
|
31 CollisionProcessor::register_components(&mut data); |
|
32 |
47 Self { |
33 Self { |
|
34 data, |
48 allocator: GearAllocator::new(), |
35 allocator: GearAllocator::new(), |
49 physics: PhysicsProcessor::new(), |
36 physics: PhysicsProcessor::new(), |
50 collision: CollisionProcessor::new(world_size), |
37 collision: CollisionProcessor::new(world_size), |
51 time: TimeProcessor::new(), |
38 time: TimeProcessor::new(), |
52 } |
39 } |
57 self.allocator.alloc() |
44 self.allocator.alloc() |
58 } |
45 } |
59 |
46 |
60 #[inline] |
47 #[inline] |
61 pub fn delete_gear(&mut self, gear_id: GearId) { |
48 pub fn delete_gear(&mut self, gear_id: GearId) { |
62 self.physics.remove(gear_id); |
49 self.data.remove_all(gear_id); |
63 self.collision.remove(gear_id); |
50 self.collision.remove(gear_id); |
64 self.time.cancel(gear_id); |
51 self.time.cancel(gear_id); |
65 self.allocator.free(gear_id) |
52 self.allocator.free(gear_id) |
66 } |
53 } |
67 |
54 |
68 pub fn step(&mut self, time_step: Millis, land: &Land2D<u32>) { |
55 pub fn step(&mut self, time_step: Millis, land: &Land2D<u32>) { |
69 let updates = self.physics.process(time_step); |
56 let updates = self.physics.process(&mut self.data, time_step); |
70 let collision = self.collision.process(land, &updates); |
57 let collisions = self.collision.process(land, &updates); |
71 let events = self.time.process(time_step); |
58 let events = self.time.process(time_step); |
72 } |
59 } |
73 |
60 |
74 pub fn add_gear_data<T>(&mut self, gear_id: GearId, data: T) |
61 #[inline] |
75 where |
62 pub fn add_gear_data<T: Clone + 'static>(&mut self, gear_id: GearId, data: &T) { |
76 T: GearData, |
63 self.data.add(gear_id, data); |
77 Self: GearDataAggregator<T>, |
|
78 { |
|
79 self.find_processor().add(gear_id, data); |
|
80 } |
64 } |
81 } |
65 } |
82 |
66 |
83 #[cfg(test)] |
67 #[cfg(test)] |
84 mod tests { |
68 mod tests { |
85 use crate::{ |
69 use crate::{ |
86 collision::{CircleBounds, CollisionData}, |
70 collision::{CircleBounds, CollisionData}, |
87 common::Millis, |
71 common::Millis, |
88 physics::PhysicsData, |
72 physics::{PositionData, VelocityData}, |
89 World, |
73 World, |
90 }; |
74 }; |
91 use fpnum::{fp, FPNum, FPPoint}; |
75 use fpnum::{fp, FPNum, FPPoint}; |
92 use integral_geometry::Size; |
76 use integral_geometry::Size; |
93 use land2d::Land2D; |
77 use land2d::Land2D; |
95 #[test] |
79 #[test] |
96 fn data_flow() { |
80 fn data_flow() { |
97 let world_size = Size::new(2048, 2048); |
81 let world_size = Size::new(2048, 2048); |
98 |
82 |
99 let mut world = World::new(world_size); |
83 let mut world = World::new(world_size); |
100 let gear_id = std::num::NonZeroU16::new(46631).unwrap(); |
84 let gear_id = world.new_gear().unwrap(); |
|
85 |
|
86 world.add_gear_data(gear_id, &PositionData(FPPoint::zero())); |
|
87 world.add_gear_data(gear_id, &VelocityData(FPPoint::unit_y())); |
101 |
88 |
102 world.add_gear_data( |
89 world.add_gear_data( |
103 gear_id, |
90 gear_id, |
104 PhysicsData { |
91 &CollisionData { |
105 position: FPPoint::zero(), |
|
106 velocity: FPPoint::unit_y(), |
|
107 }, |
|
108 ); |
|
109 |
|
110 world.add_gear_data( |
|
111 gear_id, |
|
112 CollisionData { |
|
113 bounds: CircleBounds { |
92 bounds: CircleBounds { |
114 center: FPPoint::zero(), |
93 center: FPPoint::zero(), |
115 radius: fp!(10), |
94 radius: fp!(10), |
116 }, |
95 }, |
117 }, |
96 }, |