3
3
use std:: { alloc:: Layout , any:: TypeId , mem:: size_of, ptr} ;
4
4
5
5
use anyhow:: Context ;
6
- use feather_ecs:: { Ecs } ;
6
+ use feather_ecs:: { Archetype , Ecs } ;
7
7
use feather_plugin_host_macros:: host_function;
8
8
use quill_common:: {
9
9
component:: { ComponentVisitor , SerializationMethod } ,
@@ -44,13 +44,16 @@ struct WrittenComponentData {
44
44
/// `ComponentVisitor` implementation used to write
45
45
/// component data to plugin memory.
46
46
struct WriteComponentsVisitor < ' a > {
47
+ ecs : & ' a Ecs ,
48
+ types : & ' a [ HostComponent ] ,
47
49
cx : & ' a PluginContext ,
48
50
num_entities : usize ,
49
51
}
50
52
51
53
impl < ' a > ComponentVisitor < anyhow:: Result < WrittenComponentData > > for WriteComponentsVisitor < ' a > {
52
54
fn visit < T : Component > ( self ) -> anyhow:: Result < WrittenComponentData > {
53
- let components = todo ! ( ) ;
55
+ let components = matching_archetypes ( self . ecs , self . types )
56
+ . map ( |archetype| archetype. get :: < T > ( ) . unwrap ( ) ) ;
54
57
55
58
// Write each component.
56
59
// We use a different strategy depending
@@ -65,7 +68,7 @@ impl<'a> ComponentVisitor<anyhow::Result<WrittenComponentData>> for WriteCompone
65
68
// Copy the components into the buffer.
66
69
let mut byte_index = 0 ;
67
70
for component_slice in components {
68
- for component in component_slice. as_slice :: < T > ( ) {
71
+ for component in component_slice. iter ( ) {
69
72
let bytes = component. as_bytes ( ) ;
70
73
71
74
unsafe {
@@ -86,7 +89,7 @@ impl<'a> ComponentVisitor<anyhow::Result<WrittenComponentData>> for WriteCompone
86
89
87
90
// Write components into the buffer.
88
91
for component_slice in components {
89
- for component in component_slice. as_slice :: < T > ( ) {
92
+ for component in component_slice. iter ( ) {
90
93
component. to_bytes ( & mut bytes) ;
91
94
}
92
95
}
@@ -103,12 +106,28 @@ impl<'a> ComponentVisitor<anyhow::Result<WrittenComponentData>> for WriteCompone
103
106
}
104
107
}
105
108
109
+ fn matching_archetypes < ' a > (
110
+ ecs : & ' a Ecs ,
111
+ types : & ' a [ HostComponent ] ,
112
+ ) -> impl Iterator < Item = & ' a Archetype > + ' a {
113
+ struct Has < ' a > ( & ' a Archetype ) ;
114
+ impl ComponentVisitor < bool > for Has < ' _ > {
115
+ fn visit < T : Component > ( self ) -> bool {
116
+ self . 0 . has :: < T > ( )
117
+ }
118
+ }
119
+ ecs. archetypes ( )
120
+ . filter ( move |archetype| types. iter ( ) . all ( |t| t. visit ( Has ( archetype) ) ) )
121
+ }
122
+
106
123
fn create_query_data (
107
124
cx : & PluginContext ,
108
125
ecs : & Ecs ,
109
126
types : & [ HostComponent ] ,
110
127
) -> anyhow:: Result < QueryData > {
111
- let num_entities = todo ! ( ) ;
128
+ let num_entities = matching_archetypes ( ecs, types)
129
+ . map ( |archetype| archetype. ids ( ) . len ( ) )
130
+ . sum ( ) ;
112
131
if num_entities == 0 {
113
132
return Ok ( QueryData {
114
133
num_entities : 0 ,
@@ -122,6 +141,8 @@ fn create_query_data(
122
141
let component_lens = cx. bump_allocate ( Layout :: array :: < u32 > ( types. len ( ) ) ?) ?;
123
142
for ( i, & typ) in types. iter ( ) . enumerate ( ) {
124
143
let data = typ. visit ( WriteComponentsVisitor {
144
+ ecs,
145
+ types,
125
146
cx,
126
147
num_entities,
127
148
} ) ?;
@@ -133,7 +154,15 @@ fn create_query_data(
133
154
}
134
155
135
156
let entities_ptr = cx. bump_allocate ( Layout :: array :: < EntityId > ( num_entities) ?) ?;
136
- for ( i, entity) in todo ! ( ) . enumerate ( ) {
157
+ for ( i, entity) in matching_archetypes ( ecs, types)
158
+ . flat_map ( |archetype| {
159
+ archetype
160
+ . ids ( )
161
+ . iter ( )
162
+ . map ( |id| unsafe { ecs. find_entity_from_id ( * id) } )
163
+ } )
164
+ . enumerate ( )
165
+ {
137
166
let bits = entity. to_bits ( ) . get ( ) ;
138
167
unsafe {
139
168
cx. write_pod ( entities_ptr. cast ( ) . add ( i) , bits) ?;
0 commit comments